I am trying to write a unit test for the following controller:
@RestController
@RequestMapping(value = ENDPOINT_URL)
public class MainController extends RestControllerBase {
MainService mainService;
public MainController(MainService mainService) {
this.mainService = mainService;
}
@GetMapping
public ResponseEntity<List<MainDataDto>> getDashboardData() {
checkPermission();
List<MainDataDto> result = mainService.getData();
return ResponseEntity.ok().body(result);
}
}
This is what I have so far in terms of a unit test:
class MainControllerTest {
MainController mainController;
@Test
public void test_getDashboardData_shouldReturn200Response() {
MainService mainService = Mockito.mock(MainService.class);
mainController = new MainController(mainService);
List<MainDataDto> mockData = List.of(new MainDataDto());
when(mainService.getData()).thenReturn(mockData);
Assertions.assertEquals(HttpStatus.OK, mainController.getDashboardData().getStatusCode());
}
When I run this unit test, I get the following exception:
java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
This exception is coming from checkPermission
, which is a protected method in the RestControllerBase
class. I cannot change the access modifier for this method.
I am new to writing unit tests, so I am trying to do this a small bit at a time so I can understand what I am doing. Because of the exception, I want to "figure out how to deal" with checkPermission
and (with my limited understanding) I am thinking that I can/should somehow mock this method, or something along the lines of passing this part of my controller method over.
Being that this method is protected, what is the best way to change my unit test so I do not get the exception above anymore?
@Override
it. ButSecurityContext
has public methods to set the authentication for the current thread, so you should be able to simply set it in your@BeforeEach
method and clear it in your@AfterEach
method – or have a try-finally block in your test method. See linked duplicate for the first approach.