简体   繁体   English

Mockito 模拟对象返回 null

[英]Mockito mock objects returns null

I try to implement some tests for my JSF application and for the mocks I am using mockito.我尝试为我的 JSF 应用程序和我正在使用 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.测试成功,但是当我想用getInstance方法检索实例时。 All Parameters which I have set before (via the constructor before) are null.我之前(通过之前的构造函数)设置的所有参数都是 null。 I am new to mocked objects, so is this behavior normal, or is there a mistake in my code?我是模拟对象的新手,所以这种行为正常吗,还是我的代码有错误?

It really depends on GeneralConfigService#getInstance() implementation.这真的取决于 GeneralConfigService#getInstance() 实现。 Also you can simplify your test code a lot if you use @InjectMocks annotation.如果您使用@InjectMocks注释,您也可以大大简化您的测试代码。

When using MockitoJUnitRunner you don't need to initialize mocks and inject your dependencies manually:使用MockitoJUnitRunner您不需要手动初始化MockitoJUnitRunner和注入依赖项:

@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
       ...
    }
}

Don't forget to use不要忘记使用

MockitoAnnotations.initMocks(this);

If you are Mocking object through annotation ie @Mock Objectname如果你通过注解@Mock Objectname对象,即@Mock Objectname

My problem here was the incorrect import for Test anotation:我的问题是Test注释的导入不正确:

Was曾是

import org.junit.jupiter.api.Test;

Correct正确的

import org.junit.Test;

All method calls to Mockito mocks return null by default.默认情况下,对Mockito所有方法调用都返回 null。 If you want it to return something else you need to tell it to do so via a when statement.如果您希望它返回其他内容,则需要通过when语句告诉它这样做。

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.似乎您认为以下内容会起作用……您调用setInstance然后期望getInstance返回传递给setInstance的值,因为这是 DAO 的工作方式。 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 .如果这是您正在尝试的内容,则不应通过调用getInstance测试setInstance ,因为getInstance将返回您配置模拟返回的任何内容,并且与传递给setInstance内容无关。 Instead, use verify to validate that the appropriate method of the DAO was called from the setInstance method.相反,使用verify来验证从setInstance方法调用了DAO的适当方法。

For example, if GeneralConfigService.setInstance calls GeneralConfigDAO.setInstance then your test should look like this...例如,如果GeneralConfigService.setInstance调用GeneralConfigDAO.setInstance那么你的测试应该是这样的......

@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...另外,如果gen是一个模拟(通过@Mock ),为什么要通过gen = createGeneralConfigs...将它分配给其他东西gen = createGeneralConfigs...

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.该线程是一个旧线程,但我遇到了与 junit5 (v5.8.2) 和 mockito (mockito-core:jar:4.5.1) 相同的问题,这里的答案都没有帮助我。 After a 1.5 hours search I found this article:经过 1.5 小时的搜索,我找到了这篇文章:

https://mincong.io/2020/04/19/mockito-junit5/ 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):作为新的依赖项,我用以下注释注释了我的 class (并且我删除@RunWith(MockitoJUnitRunner.class)注释):

@ExtendWith(MockitoExtension.class)

Please find the explanation in the article.请在文章中找到解释。 I hope this help to others as well!我希望这对其他人也有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM