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

+3


source to share


3 answers


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.

+2


source


Don't test callBackendService () if it's just an implementation detail. If it's so complex that it deserves its own testing, refactor it into a separate class.



+1


source


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()

.

+1


source







All Articles