我在春季应用程序中编写服务层的单元测试 这是我的服务类
@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;
}
}
这是我的测试类
@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);
}
}
它工作正常但我没有问题
Autowire
服务类?我在init()
方法中使用构造函数来创建服务对象。 Autowire
元素?对于前StubRequestService
我需要在调用测试方法之前明确设置的自动装配RequestDao
,否则它会nullPointerException
requestDao
null
StubRequestService.getRequest
{{1}}方法。 答案 0 :(得分:7)
你的考试没问题。它甚至不必具有@ContextConfiguration
注释。
像Spring这样的依赖注入框架的全部意义是能够通过简单地实例化它们,设置模拟依赖项,然后调用它们的方法来单元测试服务。
你正确地做到了。对于此类单元测试,您不需要具有Spring上下文。这就是为什么他们被称为单元测试:他们独立测试它的所有实际依赖,包括Spring。
附注:假设您正在使用JUnit,则应交换assertXxx方法的参数。预期值出现在实际值之前。当断言失败并且你有一个像“期待6但是3”而不是“期待3但是6”的消息时,它变得很重要。
答案 1 :(得分:3)
如果您真的觉得它会让您的测试更容易理解 - 您可以初始化弹簧上下文并从那里获取所有对象。但是,通常需要专门为测试创建一个单独的弹簧配置XML文件,因此我不推荐它。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml");
stubRequestService = (RequestService)applicationContext.getBean("myRequestServiceBean");
(和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);
}
}
现在,我们可以在这里写什么测试?
DataAccessLayer
是否将对象从模拟的 WS正确转换为我们的域对象。ViewLayer
是否正确格式化了提供给他的对象并将其写入模拟输出流。Controller
是否从模拟 DataAccessLayer
获取对象,并将其正确处理并发送至模拟 ViewLayer
。 答案 2 :(得分:3)
或者您可以使用springockito https://bitbucket.org/kubek2k/springockito/wiki/Home,它会让你的测试变得更干净