Saad
Saad

Reputation: 907

Initializing a mock object internals before injecting it with @InjectMocks

I have something like

private static final CustomObject ObjectA = new CustomObject();

    @Mock
    Foo1 foo1;

    @Mock
    Foo2 Foo2 = new Foo2(ObjectA);

    @Mock
    Foo3 foo3;

    @InjectMocks
    ContainerClass container;

I want to initialize Foo2 with ObjectA before it gets injected in container. The above code is not working.

EDIT: I am trying to mock Foo2 but there is an internal object of Foo2 which i want to initialize with a real object, so when i call methods of Foo2, this internal object is utilized to give me results i need based on the values i provided during its construction.

Upvotes: 6

Views: 8446

Answers (2)

Jon Thoms
Jon Thoms

Reputation: 10777

Code style notwithstanding, the problem you have is that Foo2 isn't really a mock, because you're explicitly instantiating it. If you really want to use a "real" Foo2 instance that is instantiated with the Object2 instance, then consider using a @Spy annotation on Foo2. Then, the @InjectMocks annotation should do what you are expecting.

Upvotes: 0

davidxxx
davidxxx

Reputation: 131486

The above code is not working.

1) @InjectMocks uses much "magic" and is not necessary the clearest and debugable way to setup the mocks of the object under test.
Under the hoods, it tries multiple things : constructor injection, property setter injection, field injection.
But if it fails to inject, that will not report failure :

If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.

As alternative you could so explicitly set the dependencies of the object under test.

2) Side but important note : name your variables with a lowercase as first letter. Naming them with the class name is not readable and conventional.

3) This doesn't make sense :

@Mock
Foo2 Foo2 = new Foo2(ObjectA);

You instantiate Foo2 that is then replaced by a Mockito mock.
Mocking Foo2 behavior but letting its ObjectA dependency be a no mock object is not really logic.
By doing that, you don't mock really the dependencies of the object under test as your calling pattern is :

object under test -> mock dep1 -> real object dep2

In this case, writing an integration test (without mocks) makes more sense.

As you unit test ContainerClass, you will test only the ContainerClass behavior.
The ObjectA method which you would like to get the result should be a call of Foo2 to ObjectA which you mock the call to Foo2 in your test.
Note that you don't need to mock ObjectA if you mock the method of its caller.

Here is a example :

public class Foo2{

    private ObjectA objectA;

    public Foo2(ObjectA objectA){
       this.objectA = objectA;
    }

    public Bar callObjectA(){
         return objectA.foo();
    }
}

What you need to mock here is callToObjectA().

@Mock
Foo1 foo1;

@Mock
Foo2 foo2;

@Test
public void myMethod(){
   ContainerClass container = new ContainerClass(foo1, foo2);
   Bar mockedBar = new Bar(....);
   Mockito.when(foo2.callObjectA()).thenReturn(mockedBar);
   // invoke the method under test
   container.myMethod();
   // assertions ...
}

Upvotes: 2

Related Questions