Java 使用MockitoJUnitRunner运行测试时无法验证断言

Java 使用MockitoJUnitRunner运行测试时无法验证断言,java,spring-boot,testing,junit,mockito,Java,Spring Boot,Testing,Junit,Mockito,有没有办法在类上不使用@RunWithMockitoJUnitRunner注释来模拟存储库 我有一个测试通过了,没有注释,但是失败了。没有它,我的回购测试就不起作用。这是第二十二条军规 当我使用该注释时,测试中的When方法不再具有存根行为,mock什么也不做,尽管设置了break ppoints,并且这些断点被命中,指示行/方法已运行,但verify…,timesx语句表示被模拟的对象从未与该方法交互。我一直在想为什么使用@RunWithMockitoJUnitRunner注释会使Mockit

有没有办法在类上不使用@RunWithMockitoJUnitRunner注释来模拟存储库

我有一个测试通过了,没有注释,但是失败了。没有它,我的回购测试就不起作用。这是第二十二条军规

当我使用该注释时,测试中的When方法不再具有存根行为,mock什么也不做,尽管设置了break ppoints,并且这些断点被命中,指示行/方法已运行,但verify…,timesx语句表示被模拟的对象从未与该方法交互。我一直在想为什么使用@RunWithMockitoJUnitRunner注释会使Mockito最简单的部分无法工作

我找不到任何关于这个问题的帖子,但也许有人知道更好的关键字。这听起来像是一个已知的问题吗

这是我的测试:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;

// toggling this below annotation is the source of grief.
//@RunWith(MockitoJUnitRunner.class)
public class LoadEditEntityChangeLogServiceImplTest {

    @InjectMocks
    private ServiceImpl serviceMock;

    @Mock
    private EditStepRepository editStepRepository;

    @Mock
    private EditMapper editMapper;

    @Before
    public void init() {
        initMocks(this);
    }


    @Test // when the RunWith is commented out, this passes. When it is not, the test fails the verify assert. 
    public void mapEditEntityFromAction_Test() {
        EditDTO editDTO = Mockito.mock(EditDTO.class);
        when(editDTO.getSysNum()).thenReturn((long)7334);

        EditEntity editEntity = new editEntity();
        editEntity.setSysNum(editDTO.getSysNum());

        when(editMapper.mapToEntity(eq(editDTO))).thenReturn(editEntity);

        editEntity response = serviceMock.mapEditEntityFromAction(editDTO);

        verify(loadEditMapper, times(1)).mapToEntity(eq(loadEventDTO));
        assertEquals(loadEventDTO.getSystemNumber(), response.getSystemNumber());
    }

    @Test // this will fail without the @RunWith as the mocked repo will be null and throws NullPointerException when used.
    public void updateConvertedEventSegment_Test() {
        EditEntity editEntity = new EditEntity();
        EditStepEntity editStepEntity = new EditStepEntity();
        editEntity.setEditStep(editStepEntity);

        doReturn(editStepEntity).when(editStepRepository).save(any());

        serviceMock.updateEditStep(editEntity);

        verify(editEntity, times(1)).getEditStep();
        verify(editStepRepository, times(1)).save(eq(editStepEntity));
    }
}

你应该了解这个跑步者实际上做了什么:

基本上它允许用mockito注入mockito准备的mock。mock。。。进入带有@Mock注释的测试字段。在问题中,由于您已经注释掉了跑步者,所有这些字段都将为空

当您使用@InjectMocks注释某个对象时,它将把mock注入到注释引用类型的对象的字段中

这里还有一点需要澄清:MockitoAnnotations.initMocks这将与runner的功能相同,因此不需要同时包含这两个功能。如果由于某种原因无法使用runner,例如必须使用另一个runner,则应使用initMocks

现在,你问:

有没有办法在类上不使用@RunWithMockitoJUnitRunner注释来模拟存储库

答案是-是的,你可以,事实上你不必使用跑步者,有时它更方便

所以,假设你真的使用这个运行程序,真正的问题是你说我的存储库不工作到底是什么意思。这是否意味着服务中存在指向此存储库及其null的引用

这是否意味着存在存储库的模拟,但当您在测试下执行调用时,模拟是不同的

您没有在代码中显示它,但我假设您有一些类似的:

public class ServiceImpl {
   private final EditStepRepository editStepRepository;

   public ServiceImpl(EditStepRepository editStepRepository) {
      this.editStepRepository = editStepRepository;
   }
   ...
}
但是如果是这样的话,一旦您创建了一个mock,并且确实应该有一个mock被注入到ServiceImpl类中,请使用调试器或其他工具检查一下,应该在存储库中指定期望值,测试中通常应该有这样的代码:

Mockito.when(editStepRepository.doSomething(...)).thenReturn(...)
您没有放置任何这些行,这就是它不起作用的原因


但总而言之,因为这个问题包含了许多不确定的技术细节,比如说,我只能说猜测…

嗨,莎拉,我想你可以尝试添加以下行:@RunWithSpringJUnit4ClassRunner.class和@Rule public MockitoRule MockitoRule=MockitoJUnit.Rule;无需添加@RunWithMockitoJUnitRunner.classI我想你可能会提到我上次的问题。我的Mock正在工作,只是有问题要模拟文档构建。你已经很好地打破了我在跑步者工作方式背后缺少的想法-0bl0702的评论也修复了它,使用了更好的runwith类。谢谢你们两位!