v1shnu
v1shnu

Reputation: 2231

PowerMockito using InjectMocks error

I have a very complicated class to write Junit test case. I decided to use PowerMockito since my class for which the test is to be run has a constructor initialization.

My main class is like this:

public class MainClass extends BaseClass{

MainClass(SomeClass class){
    super(class);
}

public void methodToBeTested(){
some code here
}

..few other methods which I am not going to test.
}

Now I have the test case written like this:

@RunWith(PowerMockRunner.class)
public class TestClass{

@Mock
OtherClassUsedInMainClass mock1;

@Mock
OtherClassUsedInMainClass mock2;

@InjectMocks
MainClass mainClass;

@Before
public void setUp() throws Exception{
    MockitoAnnotations.initMocks(this);
    PowerMockito.whenNew(MainClass.class).withArguments(Mockito.any(SomeClass.class))
            .thenReturn(mainClass);)
}

@Test
public void testMethodtobeTested(){
    ...I am using the other objects to mock data and test if this method works fine

    mainClass.methodtobeTested();
    \\This method will increment a value. I am just asserting if that value is right. 
    Assert.assertEquals(mainClass.checkCount(),RequiredCount)

}

}

I am getting a null pointer exception when running the Testcase since it tries to initialize the mainClass. It does not get mocked. I know I am doing something wrong. But I just don't know what it is.

Error:

org.mockito.exceptions.base.MockitoException: 
Cannot instantiate @InjectMocks field named 'mainClass' of type 'class com.main.MainClass'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null

Caused by: java.lang.NullPointerException
This null pointer exception is thrown from a the constructor of the BaseClass when it tries to initialize another class.

Upvotes: 3

Views: 10603

Answers (3)

Adriaan Koster
Adriaan Koster

Reputation: 16209

If you can't show us the actual code it is very hard to guess what exactly is happening. But it looks like your mock SomeClass needs some stubbed behavior to satisfy the BaseClass constructor.

For example:

// the instance of MainClass you run your tests against
private MainClass instance;

@Mock
private SomeClass someClass;
@Mock
private SomethingElse somethingElse;

@Before
public void setUp() {
    when(someClass.doSomething()).thenReturn(somethingElse);
    instance = new MainClass(someClass);
}

@Test
public void test() {
    // SETUP
    when(somethingElse.doWeirdStuff()).thenThrow(new WeirdException());

    // CALL
    instance.performTapDance();

    // VERIFY
    assertTrue(instance.isWeird());
}

Upvotes: 0

Liviu Stirb
Liviu Stirb

Reputation: 6075

This question explains the difference between @Mock and @InjectMocks:

@Mock creates a mock. @InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock (or @Spy) annotations into this instance.

MainClass constructor expects a SomeClass parameter but there isn't any mock for that.

Your code should be something like:

@RunWith(PowerMockRunner.class)
public class TestClass{

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    SomeClass mock1;

    @InjectMocks
    MainClass mainClass;

    @Before
    public void setUp() throws Exception{
    ...

Upvotes: 1

Andy Turner
Andy Turner

Reputation: 140299

Quoting this answer, which is quoting the @InjectMocks documentation:

Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. Note: If arguments can not be found, then null is passed.

So, presumably, declare a field of type SomeClass, and annotate it @Mock.

Upvotes: 0

Related Questions