[java] Mockito : how to verify method was called on an object created within a method?

I am new to Mockito.

Given the class below, how can I use Mockito to verify that someMethod was invoked exactly once after foo was invoked?

public class Foo
{
    public void foo(){
        Bar bar = new Bar();
        bar.someMethod();
    }
}

I would like to make the following verification call,

verify(bar, times(1)).someMethod();

where bar is a mocked instance of Bar.

This question is related to java unit-testing junit mockito

The answer is


Dependency Injection

If you inject the Bar instance, or a factory that is used for creating the Bar instance (or one of the other 483 ways of doing this), you'd have the access necessary to do perform the test.

Factory Example:

Given a Foo class written like this:

public class Foo {
  private BarFactory barFactory;

  public Foo(BarFactory factory) {
    this.barFactory = factory;
  }

  public void foo() {
    Bar bar = this.barFactory.createBar();
    bar.someMethod();
  }
}

in your test method you can inject a BarFactory like this:

@Test
public void testDoFoo() {
  Bar bar = mock(Bar.class);
  BarFactory myFactory = new BarFactory() {
    public Bar createBar() { return bar;}
  };

  Foo foo = new Foo(myFactory);
  foo.foo();

  verify(bar, times(1)).someMethod();
}

Bonus: This is an example of how TDD can drive the design of your code.


If you don't want to use DI or Factories. You can refactor your class in a little tricky way:

public class Foo {
    private Bar bar;

    public void foo(Bar bar){
        this.bar = (bar != null) ? bar : new Bar();
        bar.someMethod();
        this.bar = null;  // for simulating local scope
    }
}

And your test class:

@RunWith(MockitoJUnitRunner.class)
public class FooTest {
    @Mock Bar barMock;
    Foo foo;

    @Test
    public void testFoo() {
       foo = new Foo();
       foo.foo(barMock);
       verify(barMock, times(1)).someMethod();
    }
}

Then the class that is calling your foo method will do it like this:

public class thirdClass {

   public void someOtherMethod() {
      Foo myFoo = new Foo();
      myFoo.foo(null);
   }
}

As you can see when calling the method this way, you don't need to import the Bar class in any other class that is calling your foo method which is maybe something you want.

Of course the downside is that you are allowing the caller to set the Bar Object.

Hope it helps.


Solution for your example code using PowerMockito.whenNew

  • mockito-all 1.10.8
  • powermock-core 1.6.1
  • powermock-module-junit4 1.6.1
  • powermock-api-mockito 1.6.1
  • junit 4.12

FooTest.java

package foo;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

//Both @PrepareForTest and @RunWith are needed for `whenNew` to work 
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Foo.class })
public class FooTest {

    // Class Under Test
    Foo cut;

    @Mock
    Bar barMock;

    @Before
    public void setUp() throws Exception {
        cut = new Foo();

    }

    @After
    public void tearDown() {
        cut = null;

    }

    @Test
    public void testFoo() throws Exception {

        // Setup
        PowerMockito.whenNew(Bar.class).withNoArguments()
                .thenReturn(this.barMock);

        // Test
        cut.foo();

        // Validations
        Mockito.verify(this.barMock, Mockito.times(1)).someMethod();

    }

}

JUnit Output JUnit Output


The classic response is, "You don't." You test the public API of Foo, not its internals.

Is there any behavior of the Foo object (or, less good, some other object in the environment) that is affected by foo()? If so, test that. And if not, what does the method do?


Yes, if you really want / need to do it you can use PowerMock. This should be considered a last resort. With PowerMock you can cause it to return a mock from the call to the constructor. Then do the verify on the mock. That said, csturtz's is the "right" answer.

Here is the link to Mock construction of new objects


Another simple way would be add some log statement to the bar.someMethod() and then ascertain you can see the said message when your test executed, see examples here: How to do a JUnit assert on a message in a logger

That is especially handy when your Bar.someMethod() is private.


I think Mockito @InjectMocks is the way to go.

Depending on your intention you can use:

  1. Constructor injection
  2. Property setter injection
  3. Field injection

More info in docs

Below is an example with field injection:

Classes:

public class Foo
{
    private Bar bar = new Bar();

    public void foo() 
    {
        bar.someMethod();
    }
}

public class Bar
{
    public void someMethod()
    {
         //something
    }
}

Test:

@RunWith(MockitoJUnitRunner.class)
public class FooTest
{
    @Mock
    Bar bar;

    @InjectMocks
    Foo foo;

    @Test
    public void FooTest()
    {
        doNothing().when( bar ).someMethod();
        foo.foo();
        verify(bar, times(1)).someMethod();
    }
}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to unit-testing

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0 How to test the type of a thrown exception in Jest Unit Tests not discovered in Visual Studio 2017 Class Not Found: Empty Test Suite in IntelliJ Angular 2 Unit Tests: Cannot find name 'describe' Enzyme - How to access and set <input> value? Mocking HttpClient in unit tests Example of Mockito's argumentCaptor How to write unit testing for Angular / TypeScript for private methods with Jasmine Why is the Visual Studio 2015/2017/2019 Test Runner not discovering my xUnit v2 tests

Examples related to junit

Eclipse No tests found using JUnit 5 caused by NoClassDefFoundError for LauncherFactory How to resolve Unneccessary Stubbing exception JUnit 5: How to assert an exception is thrown? How do I mock a REST template exchange? Class Not Found: Empty Test Suite in IntelliJ Unable to find a @SpringBootConfiguration when doing a JpaTest Failed to load ApplicationContext (with annotation) Example of Mockito's argumentCaptor Mockito - NullpointerException when stubbing Method Spring jUnit Testing properties file

Examples related to mockito

How to resolve Unneccessary Stubbing exception How do I mock a REST template exchange? Mockito : doAnswer Vs thenReturn Example of Mockito's argumentCaptor Mockito: Mock private field initialization Mockito - NullpointerException when stubbing Method Usages of doThrow() doAnswer() doNothing() and doReturn() in mockito Java verify void method calls n times with Mockito Unfinished Stubbing Detected in Mockito How do I mock an autowired @Value field in Spring with Mockito?