Skip to content
Advertisement

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

Im currently Testing my Controller methods. In one Method I add a Reisepunkt(travelpoint) to a Reise(travel), which is already saved inside a database.

  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"));
  }

Using the generated-request.http API I can use the method to make entrys into the db. Now i wanted to write a test method just so I can get the hang of it.

      @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);
  }

I always get a NullPointerException in the lines:

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

Apperently Mockito has a problem when I map an Optional inside another Optional.map and then use given for the second Repository request. I guess there is some special way to implement the Test methode for a given Repo request inside a Optional map.

Answer

You forgot to mock ReisepunktRepository and this cause the NullPointerException

Update from

private ReisepunktRepository reisepunktRepository;

To

@Mock
private ReisepunktRepository reisepunktRepository;
Advertisement