2

I want to create JUnkt test for this endpoint:

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @PostMapping("reset_token")
    public ResponseEntity<?> resetToken(@Valid @RequestBody ResetPasswordTokenDTO resetPasswordTokenDTO, BindingResult bindResult) {

        final String login = jwtTokenProvider.getUsername(resetPasswordTokenDTO.getResetPasswordToken());
    }

Full code: Github

JUnit test:

@Test
public void resetTokenTest_NOT_FOUND() throws Exception {
    when(usersService.findByResetPasswordToken(anyString())).thenReturn(Optional.empty());

    mockMvc.perform(post("/users/reset_token")
            .contentType(MediaType.APPLICATION_JSON)
            .content(ResetPasswordTokenDTO))
            .andExpect(status().isNotFound());
}

I get NPE at this line when I run the code:

final String login = jwtTokenProvider.getUsername(resetPasswordTokenDTO.getResetPasswordToken());

How I can mock jwtTokenProvider properly? As you can see I have a file with test data which I load but the token is not extracted. Do you know how I can fix this issue?

Peter Penzov
  • 1,126
  • 134
  • 430
  • 808

2 Answers2

2

The most straightforward way is to use Mockito and create mock instances and pass it directly to your controller class using constructor injection.

However, if you do not wish to use constructor injection (I recommend you to use it though, as it is much more explicit) you need to define your beans in a separate test configuration class


@Profile("test")
@Configuration

public class TestConfiguration {
    @Bean
    public JwtTokenProvider mockJwtTokenProvider() {
        return Mockito.mock(JwtTokenProvider.class);
    }

}

Also, add the correct profile to your test class by @ActiveProfiles("test")

recrsn
  • 450
  • 5
  • 12
2

You can consider using a @MockBean directly in your test class to mock your JwtTokenProvider. @MockBean annotation is Spring-ish and is included in spring-boot-starter-test. The Spring Boot documentation summarizes it well:

Spring Boot includes a @MockBean annotation that can be used to define a Mockito mock for a bean inside your ApplicationContext. You can use the annotation to add new beans or replace a single existing bean definition. The annotation can be used directly on test classes, on fields within your test, or on @Configuration classes and fields. When used on a field, the instance of the created mock is also injected. Mock beans are automatically reset after each test method.

The @MockBean annotation will make Spring look for an existing single bean of type JwtTokenProvider in its application context. If it exists, the mock will replace that bean, and if it does not exist, it adds the new mock in the application context.

Your test class would look like this:

import org.springframework.boot.test.mock.mockito.MockBean;

@MockBean
@Qualifier("xxx") //If there is more than one bean of type JwtTokenProvider
private JwtTokenProvider jwtTokenProvider;

@Test
public void resetTokenTest_NOT_FOUND() throws Exception {

    when(jwtTokenProvider.getUsername(anyString())).thenReturn(Optional.empty());

    mockMvc.perform(post("/users/reset_token")
            .contentType(MediaType.APPLICATION_JSON)
            .content(ResetPasswordTokenDTO))
            .andExpect(status().isNotFound());
}

You might also want to check this and this.

jumping_monkey
  • 5,941
  • 2
  • 43
  • 58