sara
sara

Reputation: 11

Wanted to but not invoked. Mockito

I have a question. Maybe it is very basic. Can we do this

without actually invoking the method in our test class?

My Test class:

class Test{

Action action=new Action();

@Mock
Provider provider;

when(provider.getNames()).thenReturn(Arrays.asList("names"));
verify(provider,atLeastOnce()).getNames();

action.update();

}

As you can see, "provider" is only mocked and not explicitly called. The only way it will be called is when I invoke action.update(); I am getting the error

Wanted but not invoked: Actually, there were zero interactions with this mock. provider.getNames()

class Action{

public void update(){
Provider provider = new Provider();

List<String> l=provider.getNames();
}


}


 

Upvotes: 0

Views: 293

Answers (1)

dominicoder
dominicoder

Reputation: 10185

Your order of operations is wrong. If provider is called when action.update() is called, then you should be verifying after calling action.update():

when(provider.getNames()).thenReturn(Arrays.asList("names"));

action.update(); // Do action first

verify(provider,atLeastOnce()).getNames(); // Then verify outcome of "action"

UPDATE

Your code is not currently testable:

public void update(){
    Provider provider = new Provider();

    List<String> l=provider.getNames();
}

Your code says "when update is called, make a NEW provider and call getNames on that". Your test says "assert that this random provider that does interact with action at all is called", which will of course never pass.

You need to use dependency injection to pass in the provider you want to use to verify the interaction.

Either pass the provider to the function:

public void update(Provider provider){
    List<String> l=provider.getNames();
}

So you can test like this:

action.update(provider)

verify(provider).getNames()

OR pass the provider via constructor:

class Action {
    private final Provider mProvider;

    // Default constructor can be used in main app as usual
    public Action() {
        this(new Provider())
    }

    // Argument constructor can receive a provider that can be mocked
    public Action(Provider provider) {
         mProvider = provider;
    }

    public void update(){
        // Provider provider = new Provider(); // Don't do this

        List<String> l = mProvider.getNames(); // Use constructor provided object
    }

Then you can test this:

@Test
public void test() {
    Action action = new Action(provider); // Inject mock
    action.update();
    verify(provider).getNames(); // Now our mock will get called
}

Upvotes: 0

Related Questions