Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test for method that calls multiple other methods using Mockito

Perhaps I have completely fallen short in my search, but I cannot locate any documentation or discussions related to how to write a unit test for a Java class/method that in turn calls other non-private methods. Seemingly, Mockito takes the position that there is perhaps something wrong with the design (not truly OO) if a spy has to be used in order to test a method where mocking internal method calls is necessary. I'm not certain this is always true. But using a spy seems to be the only way to accomplish this. For example, why could you not have a "wrapper" style method that in turn relies on other methods for primitive functionality but additionally provides functionality, error handling, logging, or different branches dependent on results of the other methods, etc.?

So my question is two-fold:

  1. Is it poorly designed and implemented code to have a method that internally calls other methods?
  2. What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?

This might be a difficult request, but I would prefer for those who decide to answer to not merely re-publish the Mockito verbiage and/or stance on spies as I already am aware of that approach and ideology. Also, I've used Powermockito as well. To me, the issue here is that Mockito developed this framework where additional workarounds had to be created to support this need. So I suppose the question I am wanting an answer to is if spies are "bad", and Powermockito were not available, how is one supposed to unit test a method that calls other non-private methods?

like image 203
aquacode Avatar asked Sep 27 '12 15:09

aquacode


2 Answers

To me, this question relates strongly to the concept of cohesion.

My answer would be:

It is ok to have methods (public) that call other methods (private) in a class, in fact very often that is what I think of as good code. There is a caveat to this however in that your class should still be strongly cohesive. To me that means the 'state' of your class should be well defined, and the methods (think behaviours) of your class should be involved in changing your classes state in predictable ways.

Is this the case with what you are trying to test? If not, you may be looking at one class when you should be looking at two (or more).

What are the state variables of the class you're trying to test?

You might find that after considering the answers to these types of questions, your code becomes much easier to test in the way you think it should be.

like image 163
John Deverall Avatar answered Oct 17 '22 07:10

John Deverall


The real question should be:

What do I really want to test?

And actually the answer should be:

The behaviour of my object in response to outside changes

That is, depending on the way one can interact with your object, you want to test every possible single scenario in a single test. This way, you can make sure that your class reacts according to your expectations depending on the scenario you're providing your test with.

Is it poorly designed and implemented code to have a method that internally calls other methods?

Not really, and really not! These so called private methods that are called from public members are namely helper methods. It is totally correct to have helper methods!

Helper methods are there to help break some more complex behaviours into smaller pieces of reusable code from within the class itself. Only it knows how it should behave and return the state accordingly through the public members of your class.

It is unrare to see a class with helper methods and normally they are necessary to adopt an internal behaviour for which the class shouldn't react from the outside world.

What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?

In my humble opinion, you don't test those methods. They get tested when the public members are tested through the state that you expect out of your object upon a public member call. For example, using the MVP pattern, if you want to test user authentication, you shall not test every private methods, since private methods might as well call other public methods from an object on which depend the object under test and so forth. Instead, testing your view:

@TestFixture
public class TestView {
    @Test
    public void test() {
        // arrange
        string expected = "Invalid login or password";
        string login = "SomeLogin";
        string password = "SomePassword";

        // act
        viewUnderTest.Connect(login, password);
        string actual = viewUnderTest.getErrorMessage;

        // assert
        assertEqual(expected, actual);
    }
}

This test method describes the expected behaviour of your view once the, let's say, connectButton is clicked. If the ErrorMessage property doesn't contain the expected value, this means that either your view or presenter doesn't behave as expected. You might check whether the presenter subscribed to your view's Connect event, or if your presenter sets the right error message, etc.

The fact is that you never need to test whatever is going on in your private methods, as you shall adjust and bring corrections on debug, which in turn causes you to test the behaviour of your internal methods simultaneously, but no special test method should be written expressly for those helper method.

like image 41
Will Marcouiller Avatar answered Oct 17 '22 09:10

Will Marcouiller