Reputation: 11
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
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