Mockito + JUnit测试返回NullPointerException

I am trying to Mock classes but i keep getting a NPE. I've seen this post Mockito - NullpointerException when stubbing Method. In this post they explain this:

“尚未被存根的方法的默认返回值对于布尔型方法为false,对于返回集合或映射的方法为空集合或映射,否则为null。这也适用于when(...)内的方法调用。”

我几乎可以肯定,这也适用于我的问题。但是我找不到解决方案。我已经尝试了将近10个小时。

我也读了一些有关@Autowired和@Before的东西,显然@autowired是在@before之前创建的,这也可以解释我的NPE。

NPE抛出@Test void getPlantSpeciesById,因为foundPlantSpecies为null,plantSpeciesServiceMock.getPlanySpeciesById(1)也是如此。感觉@Before根本没有运行。

打扰一下,如果我错过了一些东西,我现在真的很累,但是我在拼命地寻找解决方案。

这是我的代码:

@SpringBootTest(classes = PlantSpeciesService.class)
@Import({TestConfig.class})
@RunWith(MockitoJUnitRunner.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class PlantSpeciesServiceTest {

@MockBean
private PlantSpeciesRepository plantSpeciesRepository;

@MockBean
private ModelMapper modelMapper;

@Autowired
private PlantSpeciesService plantSpeciesServiceMock;

@Before("com.oopa.domain.services.PlantSpeciesService")
public void setup() {
    MockitoAnnotations.initMocks(this);
    PlantSpecies tulip = new PlantSpecies();
    tulip.setId(1);
    tulip.setMinHumidity(200);
    tulip.setMaxHumidity(400);
    tulip.setName("Tulip");



    Mockito.when(plantSpeciesRepository.findById(tulip.getId())).thenReturn(
            Optional.of(this.modelMapper.map(tulip, com.oopa.dataAccess.model.PlantSpecies.class))
    );
}

@Test
void getPlantSpeciesById() {
    PlantSpecies foundPlantSpecies = plantSpeciesServiceMock.getPlantSpeciesById(1);

    System.out.println(plantSpeciesServiceMock.getPlantSpeciesById(1));
    System.out.println(foundPlantSpecies);
    System.out.println();
    assertEquals("Tulip", foundPlantSpecies.getName());
}

}

评论
  • 不好玩
    不好玩 回复

    First things first @SpringBootTest is used for integration testing, while MockitoJunitRunner is for unit testing - and you should never mix them. The difference is crucial...

    It looks like you're trying to do unit testing here, so please try to remove @SpringBootTest and other annotations - basically everything but mockito runner.

    在此步骤之后,测试将不会尝试启动spring上下文,并且从技术上讲将成为单元测试

    Now, after this step, change @MockBean to @Mock. Using @MockBean makes sense only if your test runs with spring while @Mock is the annotation honored by the mockito runner

    After this step you should stop and understand what exactly would you like to test - what is the unit here? A service? It looks like that but then - you should create an instance of the service with new and call the real method, in the question you're trying to call the method on mock, which does not sound right logically....

    最重要的是,我建议首先对如何编写单元测试(带或不带Mockito)进行适当的了解,然后再深入研究Spring Boot复杂但功能强大的集成测试框架。抱歉,答案似乎不清楚,但是我觉得问题中的代码中有太多东西看起来不对,因此无法用一两行代码来回答IMO问题。