Home > Enterprise >  Mockito Capture argument of a Constructor in mockConstruction
Mockito Capture argument of a Constructor in mockConstruction

Time:04-23

I have the following classes:

public class Bar {
  
  private final Listener mListener;
  
  public Bar(Listener listener) {
    mListener = listener;
  }

}

public class Foo {
  
  private final int mIntField;
  private final int Bar mBarObject;

  public Foo(int intField) {
    mIntField = intField;
    mBarObject = new Bar(new Listener() { ... });
  }

}

Currently, I am writing test for Foo class and since Bar is not injected, I am using mockConstruction to force all instance of Bar being created after mockConstruction call to be mocked. But I want to capture the argument to that constructor (ie Listener). How can I do that?

CodePudding user response:

You don't need to capture the Listener when you unit-testing on Foo. Because you are using Mocking framework which isolating indirect dependencies from the test class.

Let's make a simple figure as example, if your actual dependency path is like below:

Foo -> Bar -> Listener -> Other -> Other2 -> ...

When you unit-testing on Foo, using mocking framework to make a MockedBar and eliminate the dependency path of Bar. Then, the dependency path becomes very simple:

Foo -> MockedBar  

As a result, you can unit-testing your Foo easily.

In order to do that, just refactor your code slightly. First, add a package-private constructor in your Foo:

public class Foo {

    private final int mIntField;
    private final Bar mBarObject;

    public Foo(int intField) {
        mIntField = intField;
        mBarObject = new Bar(new Listener() { ... });
    }

    // package-private constructor, for test only.
    Foo(int intField, Bar bar) {
        mIntField = intField;
        mBarObject = bar;
    }
}

Second, initialize and inject the mockedBar into Foo by constructor-injection.

public class FooTest {
    
    private Foo foo;

    @Before
    public void setup() {
        int intField = 123;
        Bar mockedBar = mock(Bar.class);
        when(mockedBar.invokeListener()).thenReturn(something);
        foo = new Foo(intField, mockedBar);
    }

    @Test
    public void test_foo() {
        // test your foo
    } 
}

That's all. Now, you don't need to use the magic function mockConstruction anymore.

  • Related