spring-boot - 如何在不运行服务器的情况下对 Jersey REST API 进行单元测试?
问题描述
我正在使用一个 REST API,它使用带有 Spring Boot 的 Jersey(因此在 XML 或 Java 中没有特定的应用程序上下文)和 Spring Data JPA。
我想在 GET 和 POST 端点上编写单元测试,但是,我不想启动 Web 服务器,因为它需要太长时间。
如果我使用JerseyTest
我的 Spring Bean,则不会将其加载到上下文中。
public class InMemoryContainerPackageTest extends
JerseyTestNg.ContainerPerClassTest {
@Override
protected TestContainerFactory getTestContainerFactory() {
return new InMemoryTestContainerFactory();
}
@Override
public Application configure() {
ResourceConfig config = new ResourceConfig()
.register(SpringLifecycleListener.class)
.register(RequestContextFilter.class)
.register(this)
.register(MyController.class)
.packages("com.my.service");
return config;
}
如果我使用SpringBootTest
它启动一个大约需要 30 秒的 Web 服务器,理想情况下我希望我的所有测试在 5 秒内完成,否则开发人员将不会运行它们。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestNGClass1 extends AbstractTestNGSpringContextTests {
我认为不适MockMvc
用于泽西端点。
解决方案
如果我使用
JerseyTest
我的 Spring Bean,则不会将其加载到上下文中。
您可以做的是"contextConfig"
在您的ResourceConfig
. 该值将是一个 SpringApplicationContext
实例。因此,如果您使用 Java 配置,则只需使用AnnotationConfigApplicationContext
.
@Override
public ResourceConfig configure() {
return new ResourceConfig()
.register(TestResource.class)
.property("contextConfig",
new AnnotationConfigApplicationContext(SpringConfig.class));
}
这里,SpringConfig
是一个任意的 Spring@Configuration
类。下面是一个完整的例子。
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
public class SpringTest extends JerseyTest {
public static class MessageService {
public String getMessage() {
return "Hello World";
}
}
@Configuration
public static class SpringConfig {
@Bean
public MessageService service() {
return new MessageService();
}
}
@Path("test")
public static class TestResource {
@Autowired
private MessageService service;
@GET
public String get() {
return service.getMessage();
}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig()
.register(TestResource.class)
.property("contextConfig",
new AnnotationConfigApplicationContext(SpringConfig.class));
}
@Override
public TestContainerFactory getTestContainerFactory() {
return new InMemoryTestContainerFactory();
}
@Test
public void testIt() {
Response res = target("test")
.request()
.get();
String msg = res.readEntity(String.class);
System.out.println(msg);
assertThat(msg).isEqualTo("Hello World");
}
}
至于 JPA,您将不得不自己配置它。使用 Spring Boot 时,所有的 JPA 引导都会得到处理。如果您打算使用 Jersey 测试框架,那么您将忽略所有 Spring Boot 配置。
自己配置 JPA 真的没那么难。它基本上包括配置 a DataSource
、 a TransactionManager
、 aJpaVendorAdaptor
和 a LocalContainerEntityManagerFactoryBean
。要启用 Spring Data 存储库,您只需使用@EnableJpaRepositories
.
看看这个完整的示例配置。
另一件需要注意的事情是,当我们使用 Jersey 测试框架时,我们不会像使用 Spring Test 那样获得测试范围的事务(和回滚)。因此,当您编写测试时,您需要考虑到这一点。
推荐阅读
- mysql - Where 子句中的未知列 (as)
- c# - 有没有办法在碰撞时触发脚本?(2D,c#,unity,个人项目)
- google-sheets - 基于下拉选择的项目列表
- c++ - 多个参数包作为工厂函数参数
- arrays - TypeError:无法分配给对象“[object Array]”的只读属性“x”
- r - 将栅格数据转换为 data.frame
- angular - Power bi 日期切片器的问题
- javascript - 算法正确时元素交换不正确
- xamarin - Xamarin Realm DB 删除所有记录
- python - TensorFlow 中 tf.GradientTape 的急切执行错误