How do I write a unit test with assertions inside a testet method?
I have a problem that I like to check some values that are hidden by another method in my junit test. How would you do that. With Mokito? Inheritance?
Here's the problem:
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(...) {
...
}
}
How do you check the values that are passed to the method
callBackendService ()?
Is there a more elegant way than using a subclass?
MyService service = new MyService() {
@Override
protected void callBackendService(...) {
assertEquals(...);
...
}
}
Respectfully,
Mike
source to share
One school of thought is that you should only Unit Test public classes. So just make your statements on the ones ResponseObject
that come back from insert()
.
Otherwise, using a mocking framework like Mockito, you can decompose the callBackendService () method into your own class (for example ServiceCaller
). Then you can mock the ServiceCaller object and check the parameters passed to it.
Something like that...
public class ServiceCaller {
public callBackendService(Request request, Response response) {
...
}
}
Then your class should look something like this:
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;
}
}
And finally, the Mockito test is something like this ...
@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);
}
I missed good design using interfaces etc. for brevity, but you get the idea.
source to share
NOTE. I guess I callService()
should becallBackendService()
Within one of your own classes, focus more on testing behavior rather than interacting between these class methods. Testing (as opposed to what you are trying to do) will not allow your tests to be tightly coupled to your implementation. For example, if you try to test a method callBackendService()
and then change this implementation detail of your class, you will break your test (s). If instead you focus on testing the behavior of the method insert()
, you can change that particular call at any time, and your test will only break if you actually break the desired behavior.
Also, let's take a look at your insertion method in more detail. If you've tested the behavior of the method createRequest()
and constructor new Response()
in other tests, you already know that they produce exactly what you expect. Thus, creating a separate test that checks the method callBackendService()
, the parameters you are expecting in this case are not really testing anything new.
What you need to do is check the result of the method call insert()
.
So, the answer to your question is: don't check arguments to a method callBackendService()
.
source to share