displayH
displayH

Reputation: 31

How to mock a method whose object is initialized outside of the testing method?

I have a class as

public class Authentication {
    private Timer timer;

    public Authentication(){
        // constructor
    }

    public void authenticate(){
        // Initialize timer in this method
        timer = new RouterTimer(FAKE_PARAM);
        testingMethod();
    }

    @VisibleForTesting
    void testingMethod(){
        timer.method();
        // other stuff
    }
}

I have a Timer object as a class attribute, but it isn't initialized in constructor, it gets initialized in authenticate().

I'm writing unit test for testingMethod(), but the tests failed because the timer is null and calling the method() will throw an NullPointerException. I can't get the timer initialized with the constructor of the class. I can't call authenticate() to initialize because that method will call testingMethod().

How do I mock or do something else in this case?

Upvotes: 2

Views: 892

Answers (3)

Md. Tahmid Mozaffar
Md. Tahmid Mozaffar

Reputation: 1005

You can change your constructor to receive a Timer object and that should be provided by the upper level where this class instance is created in the code.

In your test, you can create a mock Timer object and pass it when you create the class instance.

public class Authentication {
    private Timer timer;

    public Authentication(Timer timer){
        this.timer = timer;
        // constructor
    }

    public void authenticate(){
        // Initialize timer in this method
        timer = new RouterTimer(FAKE_PARAM);
        testingMethod();
    }

    @VisibleForTesting
    void testingMethod(){
        timer.method();
        // other stuff
    }
}

In the test, create mock timer using Mockito and pass it via constructor

Timer mockTimer = Mockito.mock(Timer.class);
Authentication auth = new Authentication(mockTimer);

Upvotes: 0

aballaci
aballaci

Reputation: 1093

You generally don't unit test private methods directly. Since they are private, consider them an implementation detail. Nobody is ever going to call one of them and expect it to work a particular way. You should instead test your public interface. If the methods that call your private methods are working as you expect, you then assume by extension that your private methods are working correctly.

Upvotes: 1

Marcin Las
Marcin Las

Reputation: 33

Why are you trying to test private method? Split your code into logical parts and test them separately. Moreover, you are breaking SRP (https://en.wikipedia.org/wiki/Single-responsibility_principle). Method authenticate() should not initialize anything.

Upvotes: 1

Related Questions