我希望下面编写的测试用例是一个“干净”的测试,即测试后自动回滚数据库更改。
@Test
public void testUpdate(){
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(JacksonFeature.class);
Client client = ClientBuilder.newClient(clientConfig);
Name name = new Name(1L,"Updated","Updated");
Response response = client
.target("http://localhost:8080/jersey-spring/name/").request().header("Content-type", MediaType.APPLICATION_JSON).post(Entity.json(name));
Assert.assertTrue(response.getStatus() == 200);
}
其余服务在集成测试期间使用jetty-maven-plugin
部署。我现在面临的问题是,我无法使用 spring test
transactional
测试,这意味着测试后对数据库的任何状态更改都需要手动清理,这是非常麻烦的.
所以我的问题是,当使用 jersey
作为 REST 提供程序时,运行“干净”集成测试的建议方法是什么。我也尝试过使用JerseyTest
,但也面临同样的问题。
由于各种原因,我无法用 Spring MVC 替换 Jersey。
更新
- 不涉及任何 mock 。测试是端到端的。
- 我喜欢接近生产配置进行集成测试,因此不使用内存数据库进行集成测试。
最佳答案
我在许多 Spring+Jersey2 项目中使用了以下配置,并且效果很好。
- 使用
JerseyTest
并在您的测试类中扩展它 - 使用mockito或powermock在 REST Controller 中模拟您的服务
- 这很重要。使用内存数据库(我更喜欢 HSQLDB )并在内存数据库中创建一个针对此的测试应用程序上下文。因此您不必担心数据完整性等问题。
- 通过重写
JerseyTest
的configure()
方法来配置您的测试类,注入(inject)您的模拟并将 REST Controller 的任何相关服务绑定(bind)到 Jersey Context。
这是一个例子:
@Override
protected Application configure() {
// Bind factories of classes to be mocked.
AbstractBinder binder = new AbstractBinder() {
@Override
protected void configure() {
bindFactory(MockCrawlerManagerFactory.class).to(CrawlerManager.class);
bindFactory(MockUrlQueueServiceFactory.class).to(UrlQueueService.class);
bindFactory(MockSitemapServiceFactory.class).to(SitemapService.class);
bindFactory(MockCrawlerServiceFactory.class).to(CrawlerService.class);
bindFactory(MockUrlContentServiceFactory.class).to(UrlContentService.class);
// Other services to mock ....
}
};
// This is your main Spring application
ApplicationContext context = new AnnotationConfigApplicationContext(Bootstrap.class);
// And create your Jersey context here, register REST controller to Jersey context
return new ResourceConfig().registerClasses(RestController.class, JacksonJsonProvider.class, JacksonJaxbJsonProvider.class)
.packages("com.company.foo.crawler.rest", "com.company.foo.crawler.exception").register(binder).property("contextConfig", context);
}
- 并开始编写测试:)
示例测试:
@Test
public void testCreateCrawlerWithNoConfiguration() throws ExecutionException, InterruptedException {
String mockUrl = "/version/" + VERSION + "/crawlers";
Map<String, Object> data = new HashMap<>();
data.put("configurationId", "null");
data.put("startUrl", "http://blog.ahmetbutun.net");
Future<Response> asyncRes = target(mockUrl).request(MediaType.APPLICATION_JSON_TYPE).header("userId", MOCK_CRAWLER_VALID_USER_ID).header("token", AUTHENTICATION_HEADER)
.async().post(Entity.json(data));
RestResponse response = asyncRes.get().readEntity(RestResponse.class);
Assert.assertNotNull(response);
Assert.assertEquals(AppConstants.ERROR_CODE_INVALID_CONFIGURATION_ID_EXCEPTION, response.getStatusCode());
Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), response.getMessage().getStatus());
}
希望这有帮助。
关于spring - 使用 jersey 2 和 Spring 编写 "clean"集成测试 - REST,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38777005/