Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integration testing and spring application events

I have a spring rest controller which fires a 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));
    }
}

And I have a integration test for the controller, something like

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

Now, if I remove the event publishing line, the test successes. However, with the event, it hits error.

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: null source

I tried bunch of different things, to avoid or skip the line in testing but nothing helped. Could you please tell me what is the right way to test such code? Thanks in advance

like image 687
Imran Avatar asked Jul 16 '17 12:07

Imran


1 Answers

I have reproduced this issue locally and this exception ...

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: null source

... strongly implies that the constructor of your VehicleAddedEvent looks like this:

public VehicleAddedEvent(Vehicle vehicle) {
    super(null);
}

If you look further down the stacktrace you'll likely see something like this:

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

So, in answer to your question; the issue is not with your test, it is with the super call in the VehicleAddedEvent constructor and if you update that such that is calls super(vehicle) rather than super(null) then the event publication will not throw an exception.

This will allow your test to complete although there is nothing in your test which asserts on or verifies that this event has been published so you may want to look into adding something for that. You probably already have an implementation of ApplicationListener<Vehicle> (if not then I'm not sure what the benefit of publishing the 'vehicle event' is) so you could @Autowire that into VehicleControllerTest and verify that the vehicle event was published like this perhaps:

// 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));
like image 141
glytching Avatar answered Oct 05 '22 19:10

glytching