flo8433
flo8433

Reputation: 387

Mockito mock objects returns null

I try to implement some tests for my JSF application and for the mocks I am using mockito. (I also use spring)

@RunWith(MockitoJUnitRunner.class)
public class GeneralConfigServiceImplTest  {

    private GeneralConfigService generalConfigService;

    @Mock
    private GeneralConfigDAO generalConfigDAO;

    @Mock
    private GeneralConfig gen;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        generalConfigService = new GeneralConfigService();
        ReflectionTestUtils.setField(generalConfigService, "generalConfigDAO", generalConfigDAO);                  
    }

    @Test
    public void testAddGeneralConfigCallDAOSuccess() throws DAOException, EntityNullException, IllegalEntityArgumentException, ParseException, EntityPersistException {
        gen = createGeneralConfigs("label", "value");

        generalConfigService.setInstance(gen);
        generalConfigService.persist();
        log.info(generalConfigService.getInstance().toString());
    }
}

The test succeeds, but when I want to retrieve the instance with the getInstance method. All Parameters which I have set before (via the constructor before) are null. I am new to mocked objects, so is this behavior normal, or is there a mistake in my code?

Upvotes: 33

Views: 138881

Answers (5)

HowToTellAChild
HowToTellAChild

Reputation: 729

This thread is an old one, but I got the same problem with junit5 (v5.8.2) and mockito (mockito-core:jar:4.5.1) and none of the answers here helped me. After a 1.5 hours search I found this article:

https://mincong.io/2020/04/19/mockito-junit5/

which helped me! I used the first solution, so I added

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>2.28.2</version>
        <scope>test</scope>
    </dependency>

as new dependency and I annotated my class with the following annotation (and I removed the @RunWith(MockitoJUnitRunner.class) annotation):

@ExtendWith(MockitoExtension.class)

Please find the explanation in the article. I hope this help to others as well!

Upvotes: 3

John B
John B

Reputation: 32949

All method calls to Mockito mocks return null by default. If you want it to return something else you need to tell it to do so via a when statement.

It seems the you are thinking that the following will work... you call setInstance and then expect getInstance to return the value that was passed to setInstance since this is how the DAO would work. If this is what you are attempting, you shouldn't test setInstance by then calling getInstance since getInstance will return whatever you have configured the mock to return and will have no relation to what was passed to setInstance. Instead, use verify to validate that the appropriate method of the DAO was called from the setInstance method.

For example, if GeneralConfigService.setInstance calls GeneralConfigDAO.setInstance then your test should look like this...

@Test
public void testAddGeneralConfigCallDAOSuccess() throws DAOException, EntityNullException, IllegalEntityArgumentException, ParseException, EntityPersistException {
    gen = createGeneralConfigs("label", "value");

    generalConfigService.setInstance(gen);
    generalConfigService.persist();

    verify(genConfigDAO).setInstance(sameInstance(gen));
}

Also, if gen is a mock (via @Mock) why are you assigning it to something else via gen = createGeneralConfigs...

Upvotes: 8

FabianoLothor
FabianoLothor

Reputation: 2977

My problem here was the incorrect import for Test anotation:

Was

import org.junit.jupiter.api.Test;

Correct

import org.junit.Test;

Upvotes: 15

Swarit Agarwal
Swarit Agarwal

Reputation: 2648

Don't forget to use

MockitoAnnotations.initMocks(this);

If you are Mocking object through annotation i.e. @Mock Objectname

Upvotes: 13

hoaz
hoaz

Reputation: 10153

It really depends on GeneralConfigService#getInstance() implementation. Also you can simplify your test code a lot if you use @InjectMocks annotation.

When using MockitoJUnitRunner you don't need to initialize mocks and inject your dependencies manually:

@RunWith(MockitoJUnitRunner.class)
public class GeneralConfigServiceImplTest  {

    @InjectMocks
    private GeneralConfigService generalConfigService;

    @Mock
    private GeneralConfigDAO generalConfigDAO;

    @Test
    public void testAddGeneralConfigCallDAOSuccess() {
       // generalConfigService is already instantiated and populated with dependencies here
       ...
    }
}

Upvotes: 23

Related Questions