2017-07-16 2 views
4

j'ai un contrôleur de repos de ressort qui tire un ApplicationEventtests d'intégration et d'événements d'application printemps

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

Et j'ai un test d'intégration pour le contrôleur, quelque chose comme

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

Maintenant, si je retire la ligne de publication de l'événement, les succès du test. Cependant, avec l'événement, il rencontre une erreur. J'ai essayé beaucoup de choses différentes, pour éviter ou passer la ligne dans les tests, mais rien n'y a aidé. Pourriez-vous s'il vous plaît me dire quelle est la bonne façon de tester un tel code? Merci à l'avance

+4

Serait-il possible de voir la trace complète de la pile? –

Répondre

5

Je reproduis cette question au niveau local et cette exception ...

org.springframework.web.util.NestedServletException: traitement Échec de la demande; exception imbriquée est java.lang.IllegalArgumentException: Source null

... fortement implique que le constructeur de votre VehicleAddedEvent ressemble à ceci:

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

Si vous regardez plus bas la stacktrace vous » Vous verrez probablement quelque chose comme ceci:

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

Donc, en réponse à votre question; le problème n'est pas avec votre test, il est avec le super appel dans le constructeur VehicleAddedEvent et si vous mettez à jour cela tel qu'appelle super(vehicle) plutôt que super(null) alors la publication d'événement ne lèvera pas une exception.

Cela permettra à votre test de se terminer bien qu'il n'y ait rien dans votre test qui affirme ou vérifie que cet événement a été publié, donc vous pouvez vouloir ajouter quelque chose pour cela. Vous avez probablement déjà une implémentation de ApplicationListener<Vehicle> (sinon je ne sais pas quel est l'avantage de publier l'événement 'véhicule') donc vous pouvez @Autowire cela en VehicleControllerTest et de vérifier que l'événement du véhicule a été publié comme ceci peut-être:

// 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)); 
+0

Je ne passais pas explicitement par null, mais quand vous avez indiqué cela, je vois que le paramètre que je passe est en train de devenir nul. Donc, pourquoi c'est nul est une autre histoire, mais avec une valeur nulle, cela fonctionne. Merci. – Imran