2016-04-05 4 views
3

Я использую весеннюю загрузку 1.3.0 для приложения для отдыха. Я пытаюсь создать интеграционный тест, используя RestAssured. У меня проблема с @Context. Мне не нужно вводить контроллер для получения URI.@Context имеет значение null во время теста интеграции

Вот тестовый класс:

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

Вот класс обслуживания (InvoiceRestService.java):

@Autowired 
private InvoiceController invoiceController; 

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

Вот контроллер (InvoiceController расширение RestController):

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

Здесь где произошла ошибка (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); 
} 

Вот журнал ошибок:

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 

ли кто-нибудь столкнуться с этим? Как решить эту проблему?

+1

инъекция поле вызывает все виды проблем. Передача запроса в качестве параметра метода проще и надежнее. – chrylis

+1

Я сделал это, прежде чем публиковать этот вопрос. – Leo

ответ

3

Оказывается, что ваши контроллеры больше похожи полезных классов и что ваш служба фактически контроллер. Поэтому в этом отношении ваш InvoiceController, скорее всего, не является корневым ресурсом JAX RS.

Я думаю, что самое простое решение (если вы хотите, чтобы продолжать двигаться по этому пути), чтобы удалить @Context private HttpServletRequest request; декларацию в RestController и переместить его в InvoiceRestService так:

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

Затем вам нужно пройти request к вашей утилите InvoiceController.

Но ... самым элегантным решением является просто, чтобы JAX RS проанализировал идентификатор с входящего пути. С @Path вы можете определить заполнители для именованных сегментов пути и имеете те сегменты, инжектированные в ваших JAX RS оконечные методы, как это:

@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

Спасибо Сэму, мы пробовали все вышеперечисленные и все работы, но реальная причина, по которой мы используем такой контекст, заключается в том, что мы захватываем UserPrincipal из запроса, который содержит информацию, которая аудит. Вместо того, чтобы передавать информацию аудита в каждый запрос, контроллеры просто расширяют RestController. – Leo

+0

@Leo Так что, возможно, вам нужен совет '@ ModelAttribute'? – chrylis

0

Начиная с REST Assured 2.2 вы можете использовать RestAssuredMockMvc от модуля spring-mock-mvc и не запускать веб-сервер для проведения тестов.

@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

Использование @Autowired аннотаций для запроса

@Autowired 
private HttpServletRequest request; 
+0

Он получил инъекцию, но ввел новую ошибку: java.lang.IllegalStateException: Текущий запрос не является запросом сервлета \t в org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes (WebApplicationContextUtils.java:311) \t в орге .springframework.web.context.support.WebApplicationContextUtils.access $ 400 (WebApplicationContextUtils.java:64) \t at org.springframework.web.context.support.WebApplicationContextUtils $ RequestObjectFactory.getObject (WebApplicationContextUtils.java:325) – Leo

Смежные вопросы