2016-10-17 3 views
2

저지 버전 2.23.2를 사용하고 있는데 JerseyTest을 사용하여 유효성 검사가 실패 할 때 응답을 테스트하는 방법을 알 수 없습니다. 어떤 이유로 든 아래의 테스트는 ConstraintViolationException을 던지고 400 잘못된 요청을 반환하는 대신 ProcessingException으로 래핑됩니다. ProcessingException이 던져 졌는지 확인하기 위해 테스트를 수정할 수는 있지만 실제로 응답을 테스트하고 싶습니다. Grizzly에서 JerseyTest없이 HelloResource을 실행하면 적절한 400 요청 요청이 잘못되었습니다. 아래의 badRequestResponse() 시험을 수정하는 방법에 대한 아이디어가 있습니까?JerseyTest가 400 Bad Request를 반환하는 대신 ConstraintViolationException을 throw하는 이유는 무엇입니까?

javax.ws.rs.ProcessingException: 
Exception Description: Constraints violated on marshalled bean: 
[email protected] 
-->Violated constraint on property name: "Name is a required field.". 
Internal Exception: javax.validation.ConstraintViolationException 

    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:261) 
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684) 
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228) 
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444) 
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343) 
    at example.BadRequestTest.badRequestResponse(BadRequestTest.java:70) 
    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:498) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) 
    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:498) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) 
Caused by: Exception [EclipseLink-7510] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.BeanValidationException 
Exception Description: Constraints violated on marshalled bean: 
[email protected] 
-->Violated constraint on property name: "Name is a required field.". 
Internal Exception: javax.validation.ConstraintViolationException 
    at org.eclipse.persistence.exceptions.BeanValidationException.constraintViolation(BeanValidationException.java:53) 
    at org.eclipse.persistence.jaxb.JAXBBeanValidator.buildConstraintViolationException(JAXBBeanValidator.java:385) 
    at org.eclipse.persistence.jaxb.JAXBBeanValidator.validate(JAXBBeanValidator.java:273) 
    at org.eclipse.persistence.jaxb.JAXBMarshaller.validateAndTransformIfNeeded(JAXBMarshaller.java:588) 
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:481) 
    at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:949) 
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:265) 
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250) 
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) 
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130) 
    at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:517) 
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:499) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:388) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285) 
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252) 
    ... 39 more 
Caused by: javax.validation.ConstraintViolationException 
    at org.eclipse.persistence.jaxb.JAXBBeanValidator.buildConstraintViolationException(JAXBBeanValidator.java:383) 
    ... 52 more 
+0

문제를 재현 할 수 없습니다. 테스트는 실패합니다. 그러나 메소드 매개 변수에'@ Valid' 주석을 잊어 버린 경우에만 가능합니다. 그래서 당신은 400을 기대할 때 200을 얻습니다. 그 외에는 테스트가 작동합니다. Jersey 2.23을 사용하고 있습니다. 어떤 버전을 사용하고 있습니까? –

+0

자세한 내용을 포함하도록 게시물을 업데이트했습니다. Jersey 2.23.2를 사용하고 있습니다. 내가'@ Valid' 주석을 잊어 버린 것은 맞습니다 (Good catch!). 그러나, 나는 그것을 나의 시험에 추가했고, 같은 문제를 아직도 가지고있다. 게시물의 예외 사본도 추가했습니다. – Maboi

+0

서버가 아닌 클라이언트 측 오류와 비슷합니다. 요청이 진행되지 않습니다. 빈을 사용하지 않으면 작동합니다. 그냥 문자열을 사용하십시오. Entity.json (new ObjectMapper(). writeValueAsString (new Hello (null))); –

답변

1

이것은 클라이언트 측의 문제 :

package example; 

import org.glassfish.jersey.server.ResourceConfig; 
import org.glassfish.jersey.server.ServerProperties; 
import org.glassfish.jersey.test.JerseyTest; 
import org.junit.Test; 

import javax.validation.Valid; 
import javax.validation.constraints.NotNull; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.client.Entity; 
import javax.ws.rs.core.Application; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 

import static org.junit.Assert.assertEquals; 

public class BadRequestTest extends JerseyTest { 
    @XmlAccessorType(XmlAccessType.FIELD) 
    public static class Hello { 
     @NotNull(message = "Name is a required field.") 
     private final String name; 

     private Hello() { 
      this(null); 
     } 

     public Hello(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 
    } 

    @Path("hello") 
    public static class HelloResource { 
     @POST 
     public String sayHelloToMe(@Valid Hello hello) { 
      return "Hello " + hello.getName() + "!"; 
     } 
    } 

    @Override 
    protected Application configure() { 
     return new ResourceConfig(HelloResource.class).property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); 
    } 

    /** Test OK Response. This Works!*/ 
    @Test 
    public void okResponse() { 
     Response response = target("hello") 
       .request(MediaType.TEXT_PLAIN) 
       .post(Entity.json(new Hello("Tiny Tim"))); 

     assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); 
     assertEquals("Hello Tiny Tim!", response.readEntity(String.class)); 
    } 

    /** Test Bad Request Response. This Fails! */ 
    @Test 
    public void badRequestResponse() { 
     Response response = target("hello") 
       .request(MediaType.TEXT_PLAIN) 
       .post(Entity.json(new Hello(null))); 

     assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); 
    } 
} 

는 여기에 내가 무엇입니까 예외입니다. MOXy가 기본적으로 bean 검증을 가지고 있음을 발견했습니다. 그래서 당신은 클라이언트에서 bean 검증을 얻고 있습니다. 따라서 클라이언트에서 오류가 발생하면서 요청이 진행되지 않습니다. 문자열을 보내어 테스트 할 수 있습니다.

Entity.json("{}") 

오류를 제거해야합니다. 그러나 주석에서 언급 한 것처럼 Bean을 사용하려면 MOXy를 사용하여 클라이언트에서 bean 유효성 검사를 비활성화해야합니다.

@Override 
protected void configureClient(final ClientConfig config) { 
    super.configureClient(config); 
    config.register(new MoxyJsonConfig() 
      .property(MarshallerProperties.BEAN_VALIDATION_MODE, 
         BeanValidationMode.NONE).resolver()); 
} 
관련 문제