2016-04-05 13 views
3

Ich verwende Springboot 1.3.0 auf einer Rest-Anwendung. Ich versuche einen Integrationstest mit RestAssured zu erstellen. Ich habe ein Problem mit dem @Context. Es wird nicht in den Controller injiziert, damit ich den URI bekomme.@Context ist Null während des Integrationstests

Hier ist die Testklasse:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
@WebIntegrationTest("server.port=8080") 
@ActiveProfiles(value = {"testing"}) 
public class InvoiceRestServiceIT { 

    private static String INVOICE_DATA = "<invoice data>"; 
    private static String INVOICE_URL = "/customers/1q2w3e4r/invoices"; 

    @Test 
    public void testPostInvoice() { 
     given() 
      .contentType(ContentType.JSON) 
      .accept(ContentType.JSON) 
      .body(INVOICE_DATA) 
     .expect() 
      .statusCode(200) 
      .body(containsString("entity"), containsString("id")) 
     .when() 
      .post(INVOICE_URL);; 
    } 
} 

Hier ist die Service-Klasse (InvoiceRestService.java):

@Autowired 
private InvoiceController invoiceController; 

@POST 
public EntityResponse add(InvoiceResource invoiceResource) { 
    return new EntityResponse(invoiceController.createInvoice(invoiceResource)); 
} 

Hier ist die Steuerung (InvoiceController RestController erstreckt):

protected Customer getCustomer() { 
    Customer customer = customerRepository.findOne(getCustomerId()); 
... 
} 

Hier ist, wo der Fehler auftritt (RestController.java):

@Context 
private HttpServletRequest request; 

protected String getCustomerStringId() { 
    Matcher matcher = pattern.matcher(request.getRequestURI()); //<---- Here, request object is null 
    if (!matcher.find()) { 
     throw new IllegalStateException("Cannot find customer id in request URL"); 
    } 

    return matcher.group(1); 
} 

Hier ist das Fehlerprotokoll:

java.lang.NullPointerException: null 
at org.store.rest.RestController.getCustomer(RestController.java:90) 
at org.store.rest.invoice.InvoiceController.createInvoice(InvoiceController.java:87) 
at org.store.rest.invoice.InvoiceController$$FastClassBySpringCGLIB$$2d6c1a2e.invoke(<generated>) 
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) 
at com.store.rest.invoice.InvoiceController$$EnhancerBySpringCGLIB$$90cabdc3.createInvoice(<generated>) 
at com.store.rest.invoice.InvoiceRestService.add(InvoiceRestService.java:72) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497 

Hat das jemand begegnet? Wie kann ich dieses Problem lösen?

+1

Feld Injektion verursacht alle möglichen Probleme. Das Übergeben der Anforderung als Methodenparameter ist einfacher und zuverlässiger. – chrylis

+1

Ich habe das getan, bevor ich diese Frage gepostet habe. – Leo

Antwort

3

Es scheint, dass Ihr Controller mehr wie Utility-Klassen sind und dass Ihre Service ist eigentlich ein Controller. Insofern ist Ihre InvoiceController wahrscheinlich keine JAX RS-Wurzelressource.

Ich denke, die einfachste Lösung (wenn Sie auf diesem Weg fortzufahren) ist die @Context private HttpServletRequest request; Erklärung in RestController und verschieben Sie sie in InvoiceRestService wie diese zu löschen:

@POST 
public EntityResponse add(InvoiceResource invoiceResource, @Context HttpServletRequest request) { 
    return new EntityResponse(invoiceController.createInvoice(invoiceResource, request)); 
} 

Sie werden dann die passieren müssen request zu Ihrem InvoiceController Dienstprogramm.

Aber ... die eleganteste Lösung ist, JAX RS die ID vom eingehenden Pfad parsen zu lassen. Mit @Path können Sie Platzhalter für benannte Segmente des Pfades definieren und diese Segmente in Ihre JAX RS Endpunkt Methoden wie diese injiziert haben:

@Path("/customers/{customerId}/invoices") 
public class InvoiceRestService { 

    @POST 
    public EntityResponse add(@PathParam("customerId") String customerId, InvoiceResource invoiceResource) { 
    return new EntityResponse(invoiceController.createInvoice(invoiceResource, customerId)); 
    } 
} 
+1

Danke Sam, wir haben alle oben genannten und alle funktioniert versucht, aber der wahre Grund, warum wir den Kontext verwenden, ist, dass wir das UserPrincipal aus der Anfrage erfassen, die Informationen enthält auditiert. Statt die Audit-Informationen in jede Anfrage zu übertragen, erweitern die Controller den RestController. – Leo

+0

@Leo Vielleicht möchten Sie '@ ModelAttribute' Rat? – chrylis

0

Beginnend mit REST Assured 2.2 können Sie RestAssuredMockMvc aus dem spring-mock-mvc Modul verwenden und vermeiden, den Webserver zu starten, um die Tests durchzuführen.

@RunWith(SpringJUnit4ClassRunner.class) 
@WebAppConfiguration 
@ContextConfiguration(classes = Application.class, 
    loader = AnnotationConfigWebContextLoader.class) 
public class ApplicationTest { 
    @Autowired 
    private WebApplicationContext wac; 

    @Before 
    public void setUp() { 
     RestAssuredMockMvc.webAppContextSetup(wac); 
    } 

    @Test 
    public void test() { 
     // your REST Assured test for any controller 
    } 
} 
0

Verwenden @Autowired Anmerkung zur Anfrage

@Autowired 
private HttpServletRequest request; 
+0

Es wurde injiziert, sondern führte einen neuen Fehler: java.lang.IllegalStateException: aktuelle Anforderung ist kein Servlet-Anfrage \t bei org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes (WebApplicationContextUtils.java:311) \t bei org .springframework.web.context.support.WebApplicationContextUtils.access $ 400 (WebApplicationContextUtils.java:64) \t unter org.springframework.web.context.support.WebApplicationContextUtils $ RequestObjectFactory.getObject (WebApplicationContextUtils.java:325) – Leo

Verwandte Themen