使用嵌入式 Cassandra 加速 Spring MockMvc 集成测试
Speed Up Spring MockMvc Integration Test with Embedded Cassandra
我们正在使用 MockMvc Framework 来测试 Spring 带有 JUnit 的控制器。控制器 returns 一个 DefferedResult
.
mockmvc.perform
如下所示
mockMvc.perform(post("/customer")
.accept(APPLICATION_JSON)
.header(AUTH_TOKEN_KEY, "xyz")
.header(FROM_KEY, "email@gmail.com")
.content(json)
.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(request().asyncStarted());
而且要花很多时间。 我们正在使用嵌入式 cassandra,因此需要很多时间。
这个我也试过了,还是一样。
MvcResult mvcResult = mockMvc.perform(post("/customer")
.accept(APPLICATION_JSON)
.header(AUTH_TOKEN_KEY, "xyz")
.header(FROM_KEY, "email@gmail.com")
.content(json)
.contentType(APPLICATION_JSON))
.andReturn();
mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().isOk())
.andExpect(request().asyncStarted());
我进行了数百次测试,因此构建过程非常缓慢。
有没有办法,使用 JUnit 我可以说在另一个线程中执行请求并等待响应以断言结果,或者任何其他加速它的好方法。
谢谢
您是否正在执行以下操作?
运行 作为 "Spring Integration Test"?例如
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CassandraConfig.class)
public class BookRepositoryIntegrationTest {
//
}
您是否使用 @BeforeClass / @AfterClass` 注释启动和停止嵌入式 Casandra 服务器?例如
@BeforeClass
public static void startCassandraEmbedded() {
EmbeddedCassandraServerHelper.startEmbeddedCassandra();
Cluster cluster = Cluster.builder()
.addContactPoints("127.0.0.1").withPort(9142).build();
Session session = cluster.connect();
}
... and ...
@AfterClass
public static void stopCassandraEmbedded() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
有关详细信息,请参阅 http://www.baeldung.com/spring-data-cassandra-tutorial
您真的需要 Cassandra/Persistence-Layer 申请本次测试吗?
如果答案是否定的,或者如果答案不是大量的测试用例,那么您可以在 运行 测试时注入另一个持久性存储库。为此,您可以使用 Spring 的内置 Profile
功能并相应地注释您的测试,例如:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfile("StubPersistence")
public class WebLayerIntegrationTests {
...
}
然后您可以使用 Cassanda-Repository 的存根版本进行测试,允许使用静态数据:
@Profiles("StubPersistence")
@Repository
public class StubCassandaRepository {
...
}
这个 class 可以由 HashSet
或类似的简单数据结构支持,具体取决于您的用例。这种方法的可能性在很大程度上取决于您的软件架构,因此如果您不能消除 Cassandra 依赖项,则可能无法实现。
我也想知道你是否真的需要数百个测试,需要你完整的应用程序,包括 web 层。您当然可以通过支持单元测试而不是集成测试来显着加快测试速度,这样您就不需要初始化 Spring-Context。也取决于您的应用程序和软件架构。
Spring-Boot 1.4 中还将进行一些测试改进,允许您专门初始化应用程序的单个切片以进行测试(如持久性或 Web 层):
https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4
所以,我最好的建议是:
如果你想测试你的控制器,只测试你的控制器而不是你的持久层,而是将它存根。如果你想测试你的持久层,从你的持久层的接口开始,不要使用你的控制器作为测试接口。
正如我在问题中提到的那样我们正在使用嵌入式 cassandra,因此需要很多时间。
我试着在 cassandra.yaml
文件中查找内容并更改了下面的行。
commitlog_sync_batch_window_in_ms: 90
到
commitlog_sync_batch_window_in_ms: 1
就是这样,构建时间从 30 分钟减少到 2 分钟。
来自 cassandra.yaml 条评论:-
It will wait up to commitlog_sync_batch_window_in_ms
milliseconds for other writes, before performing the sync.
减少此时间后,等待时间减少,构建时间也减少。
我们正在使用 MockMvc Framework 来测试 Spring 带有 JUnit 的控制器。控制器 returns 一个 DefferedResult
.
mockmvc.perform
如下所示
mockMvc.perform(post("/customer")
.accept(APPLICATION_JSON)
.header(AUTH_TOKEN_KEY, "xyz")
.header(FROM_KEY, "email@gmail.com")
.content(json)
.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(request().asyncStarted());
而且要花很多时间。 我们正在使用嵌入式 cassandra,因此需要很多时间。
这个我也试过了,还是一样。
MvcResult mvcResult = mockMvc.perform(post("/customer")
.accept(APPLICATION_JSON)
.header(AUTH_TOKEN_KEY, "xyz")
.header(FROM_KEY, "email@gmail.com")
.content(json)
.contentType(APPLICATION_JSON))
.andReturn();
mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().isOk())
.andExpect(request().asyncStarted());
我进行了数百次测试,因此构建过程非常缓慢。
有没有办法,使用 JUnit 我可以说在另一个线程中执行请求并等待响应以断言结果,或者任何其他加速它的好方法。
谢谢
您是否正在执行以下操作?
运行 作为 "Spring Integration Test"?例如
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CassandraConfig.class) public class BookRepositoryIntegrationTest { // }
您是否使用 @BeforeClass / @AfterClass` 注释启动和停止嵌入式 Casandra 服务器?例如
@BeforeClass public static void startCassandraEmbedded() { EmbeddedCassandraServerHelper.startEmbeddedCassandra(); Cluster cluster = Cluster.builder() .addContactPoints("127.0.0.1").withPort(9142).build(); Session session = cluster.connect(); } ... and ... @AfterClass public static void stopCassandraEmbedded() { EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); }
有关详细信息,请参阅 http://www.baeldung.com/spring-data-cassandra-tutorial
您真的需要 Cassandra/Persistence-Layer 申请本次测试吗?
如果答案是否定的,或者如果答案不是大量的测试用例,那么您可以在 运行 测试时注入另一个持久性存储库。为此,您可以使用 Spring 的内置 Profile
功能并相应地注释您的测试,例如:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfile("StubPersistence")
public class WebLayerIntegrationTests {
...
}
然后您可以使用 Cassanda-Repository 的存根版本进行测试,允许使用静态数据:
@Profiles("StubPersistence")
@Repository
public class StubCassandaRepository {
...
}
这个 class 可以由 HashSet
或类似的简单数据结构支持,具体取决于您的用例。这种方法的可能性在很大程度上取决于您的软件架构,因此如果您不能消除 Cassandra 依赖项,则可能无法实现。
我也想知道你是否真的需要数百个测试,需要你完整的应用程序,包括 web 层。您当然可以通过支持单元测试而不是集成测试来显着加快测试速度,这样您就不需要初始化 Spring-Context。也取决于您的应用程序和软件架构。
Spring-Boot 1.4 中还将进行一些测试改进,允许您专门初始化应用程序的单个切片以进行测试(如持久性或 Web 层): https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4
所以,我最好的建议是: 如果你想测试你的控制器,只测试你的控制器而不是你的持久层,而是将它存根。如果你想测试你的持久层,从你的持久层的接口开始,不要使用你的控制器作为测试接口。
正如我在问题中提到的那样我们正在使用嵌入式 cassandra,因此需要很多时间。
我试着在 cassandra.yaml
文件中查找内容并更改了下面的行。
commitlog_sync_batch_window_in_ms: 90
到
commitlog_sync_batch_window_in_ms: 1
就是这样,构建时间从 30 分钟减少到 2 分钟。
来自 cassandra.yaml 条评论:-
It will wait up to
commitlog_sync_batch_window_in_ms
milliseconds for other writes, before performing the sync.
减少此时间后,等待时间减少,构建时间也减少。