Spring-Jersey 应用程序的 JerseyTest 中的资源模型验证失败
Resource model validation failure in JerseyTest for Spring-Jersey application
我有一份带注释的 Spring-泽西应用程序。我正在尝试使用 JerseyTest
为我的控制器设置单元测试。我在 运行 测试中遇到以下错误,我无法弄清楚。我错过了什么?
SEVERE: Following issues have been detected:
WARNING: No injection source found for a parameter of type public com.example.services.dto.UnitDto com.example.apis.UnitResource.getUnits(com.example.services.dto.PointDto) throws com.example.exceptions.PointOutsideBounds at index 2.
Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public com.example.services.dto.UnitDto com.example.apis.UnitResource.getUnits(com.example.services.dto.PointDto) throws com.example.exceptions.PointOutsideBounds at index 2.; source='ResourceMethod{httpMethod=GET, consumedTypes=[], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.example.apis.UnitResource, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@31a5870e]}, definitionMethod=public com.example.services.dto.UnitDto com.example.apis.UnitResource.getUnits(com.example.services.dto.PointDto) throws com.example.exceptions.PointOutsideBounds, parameters=[Parameter [type=class com.example.services.dto.PointDto, source=contains, defaultValue=null]], responseType=class com.example.services.dto.UnitDto}, nameBindings=[]}']
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:555)
控制器class如下:
@Component
@Path("/app/units")
public class UnitResource {
@Context
private UriInfo uriInfo;
@Context
private Request request;
@Inject
private UnitService unitService;
@Inject
public UnitResource(@Named("UnitService") UnitService unitService) {
this.unitService = unitService;
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Timed(absolute = true, name = "getUnitForPoint")
public UnitDto getUnits(@QueryParam("contains") @NotNull PointDto point) throws PointOutsideBounds {
return unitService.getUnitForPoint(point);
}
}
测试class如下:
public class UnitResourceTest extends JerseyTest {
@Mock
private UnitService unitService;
@Override
protected ResourceConfig configure() {
ResourceConfig rc = new ResourceConfig()
// .register(new UnitResource(Mockito.mock(UnitService.class))) -- has the same effect
.register(UnitResource.class)
.property("contextConfig", new AnnotationConfigApplicationContext(ApplicationConfiguration.class));
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
forceSet(TestProperties.CONTAINER_PORT, "0");
return rc;
}
@Before
public void setUp() throws Exception {
super.setUp();
initMocks(this);
}
@Override
protected TestContainerFactory getTestContainerFactory() {
return new InMemoryTestContainerFactory();
}
@Test
public void testGetUnit() throws PointOutsideBounds {
Response response = target()
.path("/app/units")
.queryParam("contains", new Point(0.0,0.0).toJson())
.request(MediaType.APPLICATION_JSON_TYPE)
.get();
assertThat(response.getStatus(), is(Response.Status.OK));
}
}
应用配置class是:
@Configuration
@ComponentScan("com.example")
public class ApplicationConfiguration {
@Bean(name="UnitService")
public UnitService unitService() {
return new UnitService();
}
}
我的 Gradle 测试配置依赖项是:
dependencies {
// Using junit-dep package to get junit without hamcrest dependency
testCompile("junit:junit-dep:4.8.2")
testCompile("org.hamcrest:hamcrest-all:1.3")
testCompile("org.mockito:mockito-all:1.8.4")
testCompile ('org.glassfish.jersey.test-framework:jersey-test-framework-core:2.22.2')
testCompile('org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-inmemory:2.22.2')
}
configurations {
testCompile.exclude group: 'org.glassfish.jersey.ext', module: 'jersey-spring3'
}
我找到了 and 但都没有解决我的问题。
注意: 在大多数情况下,此答案适用于所有 @XxxParam
注释参数。
PointDto
参数似乎是问题所在
public UnitDto getUnits(@QueryParam("contains") @NotNull PointDto point)
查询参数是字符串。 Jersey 能够将该字符串转换为一些基本类型,如 int
、boolean
、Date
等。但是它不知道如何从该字符串创建 PointDto
.这并不意味着我们不能使用自定义类型。我们只需要遵守一些规则:
有一个接受字符串的构造函数。然后我们需要自己从该字符串构造对象。例如
public PointDto(String param) {
Map<String, Object> map = parseJson(param);
this.field1 = map.get("field1");
this.field2 = map.get("field2");
}
辛苦了。
另一种选择是在 class 中使用静态 fromString(String)
或静态 valueOf(String)
。 Jersey 将调用此方法来构造对象。因此,例如,您可以在 PointDto
class
public static PointDto fromString(String param) {
PointDto dto = parseJson(param);
return dto;
}
你可以有一个ParamConverterProvider
。我不会举个例子,但你可以在 this good article about how you can implement it. You can also see this post
中阅读更多内容
请注意,此答案中提供的信息位于 @QueryParam
的 javadoc 中。
我有一份带注释的 Spring-泽西应用程序。我正在尝试使用 JerseyTest
为我的控制器设置单元测试。我在 运行 测试中遇到以下错误,我无法弄清楚。我错过了什么?
SEVERE: Following issues have been detected:
WARNING: No injection source found for a parameter of type public com.example.services.dto.UnitDto com.example.apis.UnitResource.getUnits(com.example.services.dto.PointDto) throws com.example.exceptions.PointOutsideBounds at index 2.
Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public com.example.services.dto.UnitDto com.example.apis.UnitResource.getUnits(com.example.services.dto.PointDto) throws com.example.exceptions.PointOutsideBounds at index 2.; source='ResourceMethod{httpMethod=GET, consumedTypes=[], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.example.apis.UnitResource, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@31a5870e]}, definitionMethod=public com.example.services.dto.UnitDto com.example.apis.UnitResource.getUnits(com.example.services.dto.PointDto) throws com.example.exceptions.PointOutsideBounds, parameters=[Parameter [type=class com.example.services.dto.PointDto, source=contains, defaultValue=null]], responseType=class com.example.services.dto.UnitDto}, nameBindings=[]}']
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:555)
控制器class如下:
@Component
@Path("/app/units")
public class UnitResource {
@Context
private UriInfo uriInfo;
@Context
private Request request;
@Inject
private UnitService unitService;
@Inject
public UnitResource(@Named("UnitService") UnitService unitService) {
this.unitService = unitService;
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Timed(absolute = true, name = "getUnitForPoint")
public UnitDto getUnits(@QueryParam("contains") @NotNull PointDto point) throws PointOutsideBounds {
return unitService.getUnitForPoint(point);
}
}
测试class如下:
public class UnitResourceTest extends JerseyTest {
@Mock
private UnitService unitService;
@Override
protected ResourceConfig configure() {
ResourceConfig rc = new ResourceConfig()
// .register(new UnitResource(Mockito.mock(UnitService.class))) -- has the same effect
.register(UnitResource.class)
.property("contextConfig", new AnnotationConfigApplicationContext(ApplicationConfiguration.class));
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
forceSet(TestProperties.CONTAINER_PORT, "0");
return rc;
}
@Before
public void setUp() throws Exception {
super.setUp();
initMocks(this);
}
@Override
protected TestContainerFactory getTestContainerFactory() {
return new InMemoryTestContainerFactory();
}
@Test
public void testGetUnit() throws PointOutsideBounds {
Response response = target()
.path("/app/units")
.queryParam("contains", new Point(0.0,0.0).toJson())
.request(MediaType.APPLICATION_JSON_TYPE)
.get();
assertThat(response.getStatus(), is(Response.Status.OK));
}
}
应用配置class是:
@Configuration
@ComponentScan("com.example")
public class ApplicationConfiguration {
@Bean(name="UnitService")
public UnitService unitService() {
return new UnitService();
}
}
我的 Gradle 测试配置依赖项是:
dependencies {
// Using junit-dep package to get junit without hamcrest dependency
testCompile("junit:junit-dep:4.8.2")
testCompile("org.hamcrest:hamcrest-all:1.3")
testCompile("org.mockito:mockito-all:1.8.4")
testCompile ('org.glassfish.jersey.test-framework:jersey-test-framework-core:2.22.2')
testCompile('org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-inmemory:2.22.2')
}
configurations {
testCompile.exclude group: 'org.glassfish.jersey.ext', module: 'jersey-spring3'
}
我找到了
注意: 在大多数情况下,此答案适用于所有 @XxxParam
注释参数。
PointDto
参数似乎是问题所在
public UnitDto getUnits(@QueryParam("contains") @NotNull PointDto point)
查询参数是字符串。 Jersey 能够将该字符串转换为一些基本类型,如 int
、boolean
、Date
等。但是它不知道如何从该字符串创建 PointDto
.这并不意味着我们不能使用自定义类型。我们只需要遵守一些规则:
有一个接受字符串的构造函数。然后我们需要自己从该字符串构造对象。例如
public PointDto(String param) { Map<String, Object> map = parseJson(param); this.field1 = map.get("field1"); this.field2 = map.get("field2"); }
辛苦了。
另一种选择是在 class 中使用静态
fromString(String)
或静态valueOf(String)
。 Jersey 将调用此方法来构造对象。因此,例如,您可以在PointDto
classpublic static PointDto fromString(String param) { PointDto dto = parseJson(param); return dto; }
你可以有一个
ParamConverterProvider
。我不会举个例子,但你可以在 this good article about how you can implement it. You can also see this post 中阅读更多内容
请注意,此答案中提供的信息位于 @QueryParam
的 javadoc 中。