xyz*_*xyz 6 spring unit-testing mockito
我在我的spring应用程序中编写服务层的单元测试.
这是我的服务类
@Service
public class StubRequestService implements RequestService {
@Autowired
private RequestDao requestDao;
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
@Override
public Request getRequest(Long RequestId) {
Request dataRequest = requestDao.find(requestId);
return dataRequest;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的测试课
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" })
public class StubRequestServiceTest {
@Mock
public RequestDao requestDao;
StubRequestService stubRequestService; // How can we Autowire this ?
@org.junit.Before
public void init() {
stubRequestService = new StubRequestService(); // to avoid this
stubRequestService.setRequestDao(dataRequestDao);
// Is it necessary to explicitly set all autowired elements ?
// If I comment/remove above setter then I get nullPointerException
}
@Test
public void testGetRequest() {
Request request = new Request();
request.setPatientCnt("3");
when(requestDao.find(anyLong())).thenReturn(request);
assertEquals(stubRequestService.getRequest(1234L).getPatientCnt(),3);
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我几乎没有问题
Autowire在测试中提供服务?我在init()方法中使用构造函数来创建服务对象. Autowire为服务类设置所有元素吗?对于前 StubRequestService已经自动连接RequestDao,我需要调用测试方法之前明确设定,否则giveds nullPointerException因为requestDao是null在StubRequestService.getRequest方法. 你的测试很好.它甚至不必有@ContextConfiguration注释.
像Spring这样的依赖注入框架的整个要点是能够通过简单地实例化它们,设置模拟依赖项,然后调用它们的方法来对单元测试服务进行单元化.
你正确地做到了.对于此类单元测试,您不需要具有Spring上下文.这就是为什么他们被称为单元测试:他们独立测试它的所有实际依赖,包括Spring.
附注:假设您正在使用JUnit,则应交换assertXxx方法的参数.预期值出现在实际值之前.当断言失败并且你有一个像"期待6但是3"而不是"期待3但是6"的消息时,它变得很重要.
如果你真的觉得这会让你的测试更容易理解 - 你可以初始化一个 spring 上下文并从那里获取所有对象。然而,通常它需要专门为测试创建一个单独的 spring 配置 XML 文件,因此我不推荐它。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml");
stubRequestService = (RequestService)applicationContext.getBean("myRequestServiceBean");
Run Code Online (Sandbox Code Playgroud)(和 3)基本上,我更喜欢完全独立地测试应用程序的每个组件,这就是为什么我不推荐我在 [1] 中描述的内容。
这意味着,您获取应用程序的一个单独的逻辑部分并仅测试它,同时完全模拟它尝试访问的所有内容。
假设您有三个课程:
//Fetches stuff from some webservice and converts to your app domain POJOs
class DataAccessLayer {
public void setWebservice(Webservice ws) {...};
public MyObject getMyObject() {...};
}
//Formats the domain POJOs and sends them to some kind of outputstream or stuff.
class ViewLayer {
public void setOutputStream(OutputStream os) {...};
public void viewMyObject(MyObject mo) {...};
}
//Main entry point of our MyObject fetch-process-display workflow
class Controller {
public void setDataAccessLayer(DataAccessLayer dal) {...};
public void setViewLayer(ViewLayer vl) {...};
public void showMyObject() {
MyObject mo = dal.getMyObject();
...some processing here maybe...
vl.viewMyObject(mo);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以在这里编写哪些测试?
DataAccessLayer正确地将对象从模拟的WS 转换为我们的域对象。ViewLayer正确格式化提供给他的对象并将其写入模拟的输出流。Controller获取对象并正确处理它并将其发送到mocked up。 DataAccessLayer ViewLayer