0

I have 2 questions:

1) In JUnit you shouldn't test or mock private methods. But how do I deal with, when they are getting called inside a public method. Let's assume I have following setup:

public void method(String value){
    if(value.contains("something")){
        doSomethingToString(value);
    }
    else{
        //do something else
    }
}

private void doSomethingToString(String value){
    Object obj = service.getObject();   //service is mocked in my test-class
    //do something with the obj and value
}

I am doing a whitebox test, so I know the methods and what's going on. Now I want to test the public method method(String value). When I now only consider what happens in there, I would get into trouble, since I need to influence what service.getObject() in my private method returns. Is it OK, when I just go on, like I would, meaning using doReturn(objectICreatedInMyTestClass).when(service.getObject()) or do I need to find another way?

2) Methods which have more than one conditions. For example:

public void method(String value){
    if(value.contains("something")){
        Object obj = service.getObj(value);
    }
    else{
        //do something else
    }

    if(obj.getAddress == null){
        //do something
    }
    else{
        //do something else
        }

    if (obj.getName == "Name") {
        // do something
    } 
    else 
    {
        // do something else
    }
}

How many times do I need to test this method? Only twice, where once all conditions return true, and second, where they all return false? Or is it advised to test every possible scenario? This would mean test with condition 1 = true, condition 2 = false, condition 3=false, and then condition 1 = true, condition 2 = true, condition 3 = false and so on (= 8 possibilites).

kryger
  • 12,906
  • 8
  • 44
  • 65
user5417542
  • 3,146
  • 6
  • 29
  • 50
  • 1
    Possible dupe of http://stackoverflow.com/questions/34571/how-to-test-a-class-that-has-private-methods-fields-or-inner-classes. That being said, yes, you should be testing the various branches of your code. https://en.wikipedia.org/wiki/Code_coverage#Basic_coverage_criteria – Nick DeFazio Nov 03 '15 at 14:55
  • The problem I have there, is that, they only use one if condition. Don't I have complete branch coverage, when in my first test for example I have value="Stringsomething", obj.getAddress equals null and obj.getName equals "Name"? There I have all conditions set to true. And in the second test i set value="String", obj.getAddress !=null and obj.getName("String"), so now they all are covered with two tests. But do I nevertheless still need to cover all the other possibilites? – user5417542 Nov 03 '15 at 15:08

1 Answers1

1

1) Should I test private methods on their own, outside of the public methods that call them?

Typically I've always followed the assumption that if the only way your code will access that method is by going through another, then that's how you should test it. My experience with testing systems has lead me to believe that this is generally the way it's done in 'the real world' as well.

If we take your example, we can assume that our first step is to write tests to thoroughly test our main method. As part of this we should be testing scenarios that include properly exercising all the conditions we could expect it to face. This will include at least a subset of the scenarios that your private method will face.

Your private method may be used by multiple (possibly wildly different) methods, so its space of possible inputs and outputs may be greater than any single public method that uses it. If you thoroughly test the public methods that use them however, you should be in the situation where you are testing all of the possible scenarios that that private method will encounter.

Because of this you shouldn't need to write tests specifically for the private method. There may be other scenarios where it is unavoidable to try and test private methods, or private classes. Usually I would argue this is because the code is simply written in a way that makes it hard/impossible and could be rewritten to make it friendlier to tests (And therefore friendlier to being updated/refactored at a later date).

2) Should all of those combinations be tested?

This depends on what is happening in the example. There are two different scenarios to consider

a) Neither of these branches have anything to do with each other. That is, what ever happens in the first set of branches will have no way of impacting the logic of what happens in the second branch.

b) Some possible implications of running any logic in either of the first set of branches would result in a different result in the logic of the code in one or more of the second branches.

This will be down to your reading and understanding what is happening in the code, so your example isn't enough to point to one or the other way of doing things.

Seb
  • 959
  • 16
  • 29
  • Thank you very much. To point 2): In my case there are no dependencies between these branches. So the first condition doesn't affect the second one and so on. – user5417542 Nov 03 '15 at 15:13
  • In that case it's probably fine that you don't test all of these different combinations. Another point to remember is that you generally want as much code coverage as you can, but that 100% code coverage doesn't automatically mean you're testing everything that you need to with your unit tests. – Seb Nov 03 '15 at 15:16
  • You say theres no dependencies in the branches but the example you provided /does/ have at least 1 dependency - the first branch is fetching the object used in the subsequent branches – tddmonkey Nov 03 '15 at 15:50
  • Ah good point, when I referred to first and second branches I forgot to include the intial one! I was referring to the ones dependent on checking the address and then name. So when I said 'first and second branches' I actually meant 'second and third branches'. Sorry for the confusion, unfortunately I don't think you can edit comments after a certain period of time so I can't change what I said. – Seb Nov 03 '15 at 16:01