使用 Mockito 测试 Spring ControllerMethod,它使用 Optional.map NullPOinterException 更改数据库中的条目

Testing a Spring ControllerMethod using Mockito which alters an entry in the db with Optional.map NullPOinterException

我目前正在测试我的控制器方法。在一种方法中,我将 Reisepunkt(travelpoint) 添加到已经保存在数据库中的 Reise(travel)。

  private final ReiseRepository repository;
  private final ReisepunktRepository reisepunktRepository;

  ReiseController(ReiseRepository reiseRepository, ReisepunktRepository reisepunktRepository) {
    this.repository = reiseRepository;
    this.reisepunktRepository = reisepunktRepository;
  }


    /**
   * Adds a new Reisepunkt to the Reise. Both have to exist in the Database already.
   * Will throw a Exception if Reise already contains same Reisepunkt.
   * @param idReisepunkt ID of the Reisepunkt.
   * @param idReise ID of the Reise.
   * @return Configured Reise with new Reisepunkt.
   */
  @PutMapping(path = "/reise/reisepunkt/{idReise}")
  Reise addReisepunkt(@RequestParam Long idReisepunkt, @PathVariable Long idReise) {
    return repository.findById(idReise).map(reise -> {
      reisepunktRepository.findById(idReisepunkt).map(reisepunkt -> {
        for (int i = 0; i < reise.getReisepunkte().size(); i++) {
          if (reisepunkt.getId().equals(reise.getReisepunkte().get(i).getId())) {
            throw new IllegalStateException("Reise already contains the Reisepunkt");
          }
        }
        reise.addReisepunkt(reisepunkt);
        return reisepunktRepository.save(reisepunkt);
      }).orElseThrow(() -> new IllegalStateException("Could not save Reisepunkt"));
      return repository.save(reise);
    }).orElseThrow(() -> new IllegalStateException("Could not add Reisepunkt to Reise"));
  }

使用生成的-request.http API 我可以使用该方法进入数据库。现在我想写一个测试方法,这样我就可以掌握它了。

      @Mock
      private ReiseRepository reiseRepository;
      private ReisepunktRepository reisepunktRepository;
      private ReiseController underTest;
    
      @BeforeEach
      void setUp() {
        underTest = new ReiseController(reiseRepository, reisepunktRepository);
      }



    @Test
    void canAddaReisepunktToReise() {
    //given
    Reisepunkt reisepunkt = new Reisepunkt(12L, 10.41f, 51.32f,
            "nutzer@web.de", "Aussicht");

    List<Reisepunkt> reisepunkte = new ArrayList<>();
    reisepunkte.add(new Reisepunkt(34L, 4.1f, 32.32f,
            "nutzer", "jas"));
    List<Reisekatalog> reisekatalogs = new ArrayList<>();
    Reise reise = new Reise(new Date(), "TestReise", true,
            reisepunkte, reisekatalogs);

    long idReise = 1;
    long idReisepunkt = 12;

    given(reiseRepository.findById(idReise)).willReturn(java.util.Optional.of(reise));
    given(reiseRepository.save(reise)).willReturn(reise);

    given(reisepunktRepository.findById(idReisepunkt))
           .willReturn(java.util.Optional.of(reisepunkt));
    given(reisepunktRepository.save(reisepunkt)).willReturn(reisepunkt);

    //when
    underTest.addReisepunkt(idReisepunkt, idReise);

    //then
    ArgumentCaptor<Reise> reiseArgumentCaptor = ArgumentCaptor.forClass(Reise.class);
    verify(reiseRepository).save(reiseArgumentCaptor.capture());
    Reise capturedReise = reiseArgumentCaptor.getValue();
    reise.addReisepunkt(reisepunkt);
    assertThat(capturedReise).isEqualTo(reise);
  }

我总是在行中得到 NullPointerException:

given(reisepunktRepository.findById(idReisepunkt))
       .willReturn(java.util.Optional.of(reisepunkt));
given(reisepunktRepository.save(reisepunkt)).willReturn(reisepunkt);

当我在另一个 Optional.map 中映射一个 Optional 然后将 given 用于第二个 Repository 请求时,Mockito 显然有问题。我想有一些特殊的方法可以在可选映射中为给定的 Repo 请求实现测试方法。

您忘记模拟 ReisepunktRepository,这导致 NullPointerException

更新自

private ReisepunktRepository reisepunktRepository;

@Mock
private ReisepunktRepository reisepunktRepository;