Java 如何在testet方法中编写带有断言的单元测试?
我的问题是,我喜欢测试junit测试中被另一个方法隐藏的一些值。你怎么能忍受那样的事情呢。和莫基托?子类化Java 如何在testet方法中编写带有断言的单元测试?,java,unit-testing,junit4,Java,Unit Testing,Junit4,我的问题是,我喜欢测试junit测试中被另一个方法隐藏的一些值。你怎么能忍受那样的事情呢。和莫基托?子类化 MyService service = new MyService() { @Override protected void callBackendService(...) { assertEquals(...); ... } } 问题是: public class MyService extends AbstractService {
MyService service = new MyService() {
@Override
protected void callBackendService(...) {
assertEquals(...);
...
}
}
问题是:
public class MyService extends AbstractService {
public ResponseObject insert(SomeData data) {
Request request = createRequest(data);
Response response = new Response();
callService(request, response);
return createResponseObject(response);
}
protected void callBackendService(...) {
...
}
}
如何测试传递给
callBackendService()
问候,
Mike如果callBackendService()只是一个实现细节,那么不要测试它。如果它是如此复杂,值得自己测试,那么将它重构成一个单独的类。一个学派的思想是,你应该只对你的公共类进行单元测试。因此,只需对从
insert()
返回的ResponseObject
执行断言即可
否则,使用类似Mockito的模拟框架,您可以将callBackendService()方法分解到它自己的类中(例如,ServiceCaller
)。然后,您可以创建一个模拟ServiceCaller对象并验证传递给它的参数
像这样的
public class ServiceCaller {
public callBackendService(Request request, Response response) {
...
}
}
public class MyService extends AbstractService {
private ServiceCaller serviceCaller;
public ResponseObject insert(SomeData data) {
Request request = createRequest(data);
Response response = new Response();
serviceCaller.callBackendService(request, response);
return createResponseObject(response);
}
public setServiceCaller(ServiceCaller caller) {
this.serviceCaller = caller;
}
}
@Test
public void testInsert() throws Exception {
// object to test
MyService ms = new MyService();
// test input values
Request req = new Request();
Response resp = new Response();
// create a mock class and inject it into your test class
ServiceCaller sc = mock(ServiceCaller.class);
ms.setServiceCaller = sc;
// execute the method under test
ms.insert(req, resp);
// now you can see if your mock was called with the expected params
verify(sc).callBackendService(req, resp);
}
那么你的班级应该是这样的
public class ServiceCaller {
public callBackendService(Request request, Response response) {
...
}
}
public class MyService extends AbstractService {
private ServiceCaller serviceCaller;
public ResponseObject insert(SomeData data) {
Request request = createRequest(data);
Response response = new Response();
serviceCaller.callBackendService(request, response);
return createResponseObject(response);
}
public setServiceCaller(ServiceCaller caller) {
this.serviceCaller = caller;
}
}
@Test
public void testInsert() throws Exception {
// object to test
MyService ms = new MyService();
// test input values
Request req = new Request();
Response resp = new Response();
// create a mock class and inject it into your test class
ServiceCaller sc = mock(ServiceCaller.class);
ms.setServiceCaller = sc;
// execute the method under test
ms.insert(req, resp);
// now you can see if your mock was called with the expected params
verify(sc).callBackendService(req, resp);
}
最后一个Mockito测试是这样的
public class ServiceCaller {
public callBackendService(Request request, Response response) {
...
}
}
public class MyService extends AbstractService {
private ServiceCaller serviceCaller;
public ResponseObject insert(SomeData data) {
Request request = createRequest(data);
Response response = new Response();
serviceCaller.callBackendService(request, response);
return createResponseObject(response);
}
public setServiceCaller(ServiceCaller caller) {
this.serviceCaller = caller;
}
}
@Test
public void testInsert() throws Exception {
// object to test
MyService ms = new MyService();
// test input values
Request req = new Request();
Response resp = new Response();
// create a mock class and inject it into your test class
ServiceCaller sc = mock(ServiceCaller.class);
ms.setServiceCaller = sc;
// execute the method under test
ms.insert(req, resp);
// now you can see if your mock was called with the expected params
verify(sc).callBackendService(req, resp);
}
为了简洁起见,我省略了使用接口等的良好设计,但你会明白的。注意:我假设
callService()
应该是callBackendService()
在您自己的一个类中,更多地关注测试行为,而不是该类方法之间的交互。测试行为(与您正试图做的相反)将防止您的测试与您的实现紧密耦合。因此,例如,如果您继续尝试测试callBackendService()
方法,然后更改类的实现细节,您将中断测试。相反,如果您专注于测试insert()
方法的行为,您可以随时修改该特定调用,并且只有在您实际破坏了所需行为的情况下,测试才会中断
此外,让我们更详细地看一下你的插入方法。如果您在其他测试中测试了
createRequest()
方法和newresponse()
构造函数的行为,那么您已经知道它们正产生您所期望的结果。因此,创建一个单独的测试来验证callBackendService()
方法是否收到了您在本例中期望的参数,实际上并不是在测试任何新的内容
您应该做的是测试调用insert()
方法的结果
因此,您的问题的答案是,不要测试
callBackendService()
方法的参数。测试callService
。做出响应
,调用该方法并进行测试。callService()应该是callBackendService()吗?