Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null after @InjectMocks

I am having some troubles passing a dependency while unit testing with JUnit.

Consider these pieces of code:

This is the dependacy injecton into the class which i want to test, lets call it Controller.

@Inject private FastPowering fastPowering;  

And this is the unit test:

@RunWith(MockitoJUnitRunner.class)
public class ControllerTest {

@Mock
FastPowering fastPower;

@InjectMocks
Controller controller;

@Test
public void test() {
    assertEquals(
            (controller.computeAnswer(new BigDecimal(2), 2)).longValue(),
            (long) Math.pow(2, 2));
    }
}

It seems that fastPower is null, please explain how to fix that. Null pointer exception , because of calling the @injected field (fastPower) inside the .computeAnswer method)

Edit:

Solved i should have read about the difference between @Mock and @Spy...

Due to a lot of comments I am adding some more context to the solution

The difference is that in mock, you are creating a complete mock or fake object while in spy, there is the real object and you just spying or stubbing specific methods of it. While in spy objects, of course, since it is a real method, when you are not stubbing the method, then it will call the real method behavior.

If fastPower is annotated as @Mock it's methods are dummy, yet controller.computeAnswer depends on them to compute. One must provide behaviour.

If spy is used without stubbing then the real implementation of fastPower is being executed which eventually returns desired value.

Another option is to use a real FastPowering instance

https://github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes) https://github.com/mockito/mockito/wiki/Mocking-Object-Creation

And some stackoverflow thread outlining the difference Mocking vs. Spying in mocking frameworks

Short Answer: Replace @Mock with @Spy and should be working fine

like image 278
radpet Avatar asked Nov 21 '14 15:11

radpet


People also ask

What is the use of @InjectMocks annotation?

@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.

What is difference between @mock and @injectmock?

@Mock is used to create mocks that are needed to support the testing of the class to be tested. @InjectMocks is used to create class instances that need to be tested in the test class. Annotated class to be tested dependencies with @Mock annotation.


2 Answers

Use MockitoAnnotations.initMocks to initiate the @Mock and @InjectMocks objects. Your test would look something like:

@Mock
FastPowering fastPower;

@InjectMocks
Controller controller;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void test() {
    ....
}
like image 134
Khalid Avatar answered Sep 27 '22 20:09

Khalid


I fixed this by removing the extraneous new instance I was creating in my @Before method (see example below). It was also fixed by moving MockitoAnnotations.initMocks(this) after initializing myClass, but since Mockito created myClass anyway, that solution was inferior.

// Note - you may need @mock(name="foo") to help mockito differentiate props
//        if they have the same type
@mock
private Thing something;

@InjectMocks
private MyClass myClass;

@Before
 public void setUp() {
    MockitoAnnotations.initMocks(this); // Moving this below the next line fixed it...
    myClass = new MyClass() // But just remove this line and let Mockito do the work
}
like image 41
AlexMA Avatar answered Sep 27 '22 20:09

AlexMA