集成测试和spring应用程序事件

Imr*_*ran 6 junit spring integration-testing mockito

我有一个弹簧控制器,它可以激活一个ApplicationEvent

@RestController
public class VehicleController {

@Autowired
private VehicleService service;

@Autowired
private ApplicationEventPublisher eventPublisher;

@RequestMapping(value = "/public/rest/vehicle/add", method = RequestMethod.POST)
public void addVehicle(@RequestBody @Valid Vehicle vehicle){
    service.add(vehicle);
    eventPublisher.publishEvent(new VehicleAddedEvent(vehicle));
    }
}
Run Code Online (Sandbox Code Playgroud)

我对控制器进行了集成测试,例如

    @RunWith(SpringRunner.class)
    @WebMvcTest(controllers = VehicleController.class,includeFilters = @ComponentScan.Filter(classes = EnableWebSecurity.class))
    @Import(WebSecurityConfig.class)

public class VehicleControllerTest {
@Autowired
private MockMvc mockMvc;

@MockBean
private VehicleService vehicleService;

@Test
public void addVehicle() throws Exception {
    Vehicle vehicle=new Vehicle();
    vehicle.setMake("ABC");
    ObjectMapper mapper=new ObjectMapper();
    String s = mapper.writeValueAsString(vehicle);

    given(vehicleService.add(vehicle)).willReturn(1);

    mockMvc.perform(post("/public/rest/vehicle/add").contentType(
            MediaType.APPLICATION_JSON).content(s))
            .andExpect(status().isOk());
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我删除事件发布行,测试成功.但是,对于该事件,它会发生错误.

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: null source
Run Code Online (Sandbox Code Playgroud)

我尝试了很多不同的东西,以避免或跳过测试中的线,但没有任何帮助.你能否告诉我测试这些代码的正确方法是什么?提前致谢

gly*_*ing 8

我已在本地复制此问题,此异常......

org.springframework.web.util.NestedServletException:请求处理失败; 嵌套异常是java.lang.IllegalArgumentException:null source

... 强烈暗示你的构造函数VehicleAddedEvent如下:

public VehicleAddedEvent(Vehicle vehicle) {
    super(null);
}
Run Code Online (Sandbox Code Playgroud)

如果你向下看堆栈跟踪,你可能会看到这样的东西:

Caused by: java.lang.IllegalArgumentException: null source
    at java.util.EventObject.<init>(EventObject.java:56)
    at org.springframework.context.ApplicationEvent.<init>(ApplicationEvent.java:42)
Run Code Online (Sandbox Code Playgroud)

那么,回答你的问题; 问题不在于你的测试,它是在VehicleAddedEvent构造函数中使用超级调用,如果你更新那些调用super(vehicle)而不是super(null)那么事件发布不会抛出异常.

这将允许您的测试完成,尽管您的测试中没有任何内容断言或验证此事件已发布,因此您可能需要考虑添加一些内容.你可能已经有了一个实现ApplicationListener<Vehicle>(如果不是那时我不确定发布'车辆事件'的好处是什么)所以你可以@Autowire进入VehicleControllerTest并验证车辆事件是这样发布的:

// provide some public accessor which allows a caller to ask your custom
// application listener whether it has received a specific event
Assert.assertTrue(applicationListener.received(vehicle));
Run Code Online (Sandbox Code Playgroud)