如何单元测试 spring 使用 power mock 启动 rest 控制器和异常处理程序

How to unit testing spring boot rest controller and exception handler using power mock

我有一个简单的 Spring 启动应用程序,其中包含员工控制器,如果过去的年份大于 2014 年,则员工名称 returns 如果它不小于 2014 年,那么我是抛出自定义异常并在异常处理程序中处理它。
我想使用 powermock 对异常流进行单元测试,但我不确定该怎么做。我浏览了一些链接但无法理解。
目前我得到 java.lang.IllegalArgumentException:需要 WebApplicationContext。

EmployeeController.java

@RestController
public class EmployeeController{

    @GetMapping(value = "/employee/{joiningYear}",produces = MediaType.APPLICATION_JSON_VALUE)
    public List<String> getEmployeeById(@PathVariable int joiningYear) throws YearViolationException {

        if(joiningYear < 2014){
            throw new YearViolationException("year should not be less than 2014");
        }else{

            // send all employee's names joined in that year 
        }
        return null;
    }
}   

异常处理程序

@RestControllerAdvice
public class GlobalControllerExceptionHandler {


    @ExceptionHandler(value = { YearViolationException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiErrorResponse yearConstraintViolationExceptio(YearViolationException ex) {

        return new ApiErrorResponse(400, 5001, ex.getMessage());
    }
}

自定义异常

public class YearViolationException extends Exception {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public YearViolationException(String message) {

        super(message);
    }

}

Junit 到单元测试异常处理程序

@RunWith(PowerMockRunner.class)
@WebAppConfiguration
@SpringBootTest
public class ExceptionControllerTest {

    @Autowired
    private WebApplicationContext applicationContext;

    private MockMvc mockMVC;

    @Before
    public void setUp() {

        mockMVC = MockMvcBuilders.webAppContextSetup(applicationContext).build();
    }

    @Test
    public void testhandleBanNotNumericException() throws Exception {

        mockMVC.perform(get("/employee/2010").accept(MediaType.APPLICATION_JSON)).andDo(print())
                .andExpect(status().isBadRequest())
        .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON));

    }
}

从您的设置来看,您根本不需要使用模拟。看起来您想加载完整的应用程序上下文并使用 mockMVC 向您的其余控制器发送请求。这其实就是和集成测试!

现在,不幸的是我们在这里使用 Spring Boot 1.3,所以我不确定 @RunWith(PowerMockRunner.class)@SpringBootTest 的组合是否真的加载了应用程序上下文。检查你的日志,看看是否有,如果没有,试试这个:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration

另一方面,如果您想进行简单的单元测试,则不需要加载应用程序上下文。相反,您可以将 @Mock@InjectMocks 的常规 Mockito 与 @RunWith(MockitoJUnitRunner.class) 结合使用,并像调用任何其他被测方法一样直接调用要测试的方法。

希望对您有所帮助。

正如其他人所说,您根本不需要 mockMVC。如果你想测试 REST 端点,你需要的是 TestRestTemplate。 Runwith SpringRunner.class 和 WebEnvironment 设置一样重要。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class RestServiceApplicationTests {

    private String baseUrl = "http://localhost:8090";

    private String endpointToThrowException = "/employee/2010";

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test(expected = YearViolationException.class)
    public void testhandleBanNotNumericException() {
        testRestTemplate.getForObject(baseUrl + endpointToThrowException, String.class);
}