如何使用其中包含受保护代码的控制器方法编写单元测试

问题描述 投票:0回答:1

我正在尝试为以下控制器编写单元测试:

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

这是我到目前为止的单元测试:

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

当我运行此单元测试时,出现以下异常:

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

这个异常来自

checkPermission
,它是
RestControllerBase
类中的受保护方法。我无法更改此方法的访问修饰符。

我是编写单元测试的新手,所以我尝试一次做一点,这样我就能理解我在做什么。由于例外,我想“弄清楚如何处理”

checkPermission
并且(以我有限的理解)我认为我可以/应该以某种方式模拟这种方法,或者类似于通过我的这一部分的方法控制器方法结束。

由于此方法受到保护,更改我的单元测试的最佳方法是什么,这样我就不会再出现上述异常了?

java spring-boot unit-testing junit mockito
1个回答
0
投票

作为短期解决方案,单元测试可以spy

MainController
,例如:

mainController = Mockito.spy(new MainController(mainService));

允许模拟被测类的某些行为。 例如:

    doNothing().when(mainController).checkPermission();

但是,由于需要测试的类的一部分不再被测试(因为它的行为被模拟),听起来该类应该被重构。 例如,无论

checkPermission()
正在做什么都可以移动到它自己的服务/组件类,并像
MainService
一样注入到控制器中。 这将通过新类的模拟来简化单元测试设置,其中测试验证了新类被调用。

© www.soinside.com 2019 - 2024. All rights reserved.