0

I have a method with a simple if/else block. In both if and else block a private method is called.

Below is the method for which I want to write unit test case.

public void enableBLEScan() {
        if (<some boolean expression which can be mocked>) {
            initializeScan();
        } else {
            stopScan();
        }
    }

I can easily stub the behaviour of boolean expression.

But I want to check method invocation inside if else block takes place correctly. How could I do that?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Hardik Trivedi
  • 5,677
  • 5
  • 31
  • 51
  • What are the two private methods doing? perhaps you could check for a condition set by those methods? or you can use reflection, see http://stackoverflow.com/questions/34571/how-to-test-a-class-that-has-private-methods-fields-or-inner-classes?rq=1 – simonv Aug 14 '16 at 12:33
  • 1
    So what's the problem? – Oliver Charlesworth Aug 14 '16 at 12:34
  • @OliverCharlesworth I want to check method invocation inside if else block takes place correctly. – Hardik Trivedi Aug 14 '16 at 12:38
  • What I'm asking is: where are you stuck? Why can't you just check for the side-effects of those methods? – Oliver Charlesworth Aug 14 '16 at 12:39
  • Yes Thats the last option @OliverCharlesworth, but I just want to know if there is a way to test method invocation only like 'verify' does. Problem with the verify method is it requires mocked object. – Hardik Trivedi Aug 14 '16 at 12:42
  • Indeed, it doesn't make sense to mock the object you're testing. – Oliver Charlesworth Aug 14 '16 at 12:43
  • 2
    You could use a spy, if your mocking framework supports it. But it's better to do what Oliver suggests. Check the side effects of the private methods. That makes your tests robust in the face of changes to your class's implementation. After all, your class's requirement isn't that `stopScan` gets called if the boolean expression is false - it's that the scan gets stopped (or whatever else `stopScan` actually does). You should _always_ test to the class's requirements, not to the code that you've written; otherwise your tests are self-fulfilling prophecies. – Dawood ibn Kareem Aug 14 '16 at 12:48

2 Answers2

1

The point is: testing if internal private methods are called ... is an anti-pattern when writing unit tests!

You do not test internal implementation details. It shouldn't matter to your tests how some "externally facing" method does what it does. In other words, you have the following choices:

  1. If you are calling methods on "fields" of your class under test, use dependency injection to insert mocked versions of the corresponding objects. Then you can verify that the expected methods are called.
  2. Check observable behavior. Meaning: call your "method under test"; and check the values returned such methods; or use other getters to inspect the internal state of your class after you made a call.

In other words: each of your "public" methods should have a clear, defined meaning. So, if you call them, they will have a defined effect; and this effect should be observed/asserted on.

It could well be that your current design really support these ideas. Then, seriously: consider stepping back and changing your design. Because: you created something that is not reasonably testable. Then chances are ... that your design has other problems, too.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
0

Checking that private methods are called is not that you should try to test in a unit test.
It's not an acceptance test. Usually, you want to test the behavior and or the result of the behavior of a class.
In your case, I see two clean possibilities :

  • change your design to have two classes and mocking the called class.

For this way of doing, I imagine you have to know.

  • make the behavior to create a result.

You could for example add a enum field ScanState in your class that you set according your logic in initializeScan() and stopScan().

ScanState example :

public enum ScanState{
  (INITIALIZED, STOPPED)
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • To directly run into the "enum" trap. If you are dealing with states, then create a **state machine**; meaning: have an abstract base class and use polymorphism to model each state as subclass. If you start using enums like this, all of a sudden you deal with switch statements all over the place. Seriously: don't go there. – GhostCat Aug 14 '16 at 14:31
  • We don't know many things about which is done in the method. So, I just gave state as an example by relying on the single information we have : `initializeScan()` and `stopScan()`. The pointer is "make the behavior to create a result". When you said `meaning: have an abstract base class and use polymorphism to model each state as subclass`. I disagree. Having a state field doesn't mean always using the state design pattern. You can use a state without overhead and without state machine if not needed. For example, a stream may have a state with a simple field. – davidxxx Aug 14 '16 at 15:11