前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Boot下如何使用自定义的测试切片

Spring Boot下如何使用自定义的测试切片

作者头像
烟雨平生
发布2023-03-07 16:17:11
1.5K0
发布2023-03-07 16:17:11
举报
文章被收录于专栏:数字化之路数字化之路
原文链接:https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4

作者:STÉPHANE NICOLL

译者:helloworldtang

Spring Boot 1.4包括对单元测试的重大支持,其中一个特性是测试切片。我想利用这个机会在这篇博客文章中,进一步解释它是什么,以及如何轻松地创建自己的切片。

测试切片是关于为您的测试创建 ApplicationContext的分段。通常,如果您想使用 MockMvc测试一个控制器,那么您肯定不希望使用数据层。相反,您可能想要mock 您的控制器使用的服务,并验证所有与web相关的交互都是按预期工作的。这可以在下面的例子中总结:

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class UserVehicleControllerTests {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    public void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
                .andExpect(status().isOk()).andExpect(content().string("Honda Civic"));
    }

}

@WebMvcTest是Spring Boot 1.4中的web测试切片。当它出现时,就相当于您告诉Spring Boot这里需要一个web环境,并且只有指定的控制器应该被实例化。因为它知道这个测试要做什么,所以它可以为您提供额外的智能决策(例如,自动配置 MockMvc,这样剩下的就是注入它)。另外,由于您的控制器也依赖 UserVehicleService,因此启动Spring Boot项目时会失败,因为 ApplicationContext中没有注册 UserVehicleService(记住,只有web基础设施和 UserVehicleController是已知的)。 @MockBean在这里用来注册一个 UserVehicleService的mock,这样它就可以透明地注入控制器中。

现在让我们看一看具体实现,以便更好地理解 Spring Boot是如何为您管理这一切的。我们的第一站是 @WebMvcTest(移除了 @Target及其它元注解):

代码语言:javascript
复制
@BootstrapWith(WebMvcTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(WebMvcTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureWebMvc
@AutoConfigureMockMvc
@ImportAutoConfiguration
public @interface WebMvcTest { ... }

这一声明可分为三个方面:

  • 自定义自动配置
  • Classpath扫描调优
  • 测试引导

自定义自动配置

Spring Boot 1.4现在定义了一个 spring-boot-test-autoconfigure模块,它提供了一组与测试相关的自动配置。这些自动配置是可组合的,可以帮助您轻松地构建自己的基础设施。

回到 @WebMvcTest,我们要做的第一件事就是禁用默认的自动配置: OverrideAutoConfiguration就是这样做的。因为默认的自动配置现在已经禁用,所以您必须选择您想要包含的相关自动配置。这三个 AutoConfigure注解为我们做了这样的事情:它们确保了web环境可用, MockMvc 被配置,并且有一个no-op缓存管理器可用。让我们看一段 AutoconfigureMockMvc的代码:

代码语言:javascript
复制
@ImportAutoConfiguration
@PropertyMapping("spring.test.mockmvc")
public @interface AutoConfigureMockMvc {

    boolean addFilters() default true;

    @PropertyMapping("webclient.enabled")
    boolean webClientEnabled() default true;

    ...
}

@ImportAutoConfiguration是一个注解,它列出了需要包含的自动配置。或者,您可以使用关键字的全限定名来提供 META-INF/spring.factories中的列表。 AutoConfigureMockMvc的定义如下所示:

代码语言:javascript
复制
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=\
org.s.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration,\
org.s.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration,\
org.s.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration,\
org.s.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration

您可以得到这样的想法:每个注解都会带来一些自动配置,您可以按照任何方式组合它们。您会注意到 WebMvcTest也有一个 ImportAutoConfiguration,但是在 spring.factories中没有相关条目。Spring Boot将在类路径中扫描所有的 spring.factories,如果需要,将 合并内容。如果您的一个模块想要向 @WebMvcTest(或 @AutoConfigureMockMvc)添加额外的行为,那么所需要的就是创建一个 META-INF/spring.factories资源文件和注册额外的自动配置类。您还可以使用 @AutoconfigureBefore@AutoconfigureAfter来指定优先级。

测试用到的自动配置也是可配置的:在类级别上的 @PropertyMapping注解将注解的属性映射到 Environment,这样自动配置代码就可以提取值并相应地调整配置。我们可以看到上面的 webClientEnabled属性在自动配置中被透明地使用:

代码语言:javascript
复制
@ConditionalOnProperty(prefix = "spring.test.mockmvc.webclient", 
        name = "enabled", matchIfMissing = true)
public class MockMvcWebClientAutoConfiguration { ... }

Classpath扫描调优

TypeExcludeFilters是一种优化类路径扫描的方法。在 @WebMvcTest 的案例中,我们只会包含某些与web相关的组件,而忽略其余的部分。这是非常强大的,因为您可以使用通常的方式进行类路径扫描,并且只包括切片所需的内容。

测试引导

最后,新的测试引导程序确保在项目中识别 @SpringBootApplication注解类(除非指定了一个)。这是一个不错的默认值,因为您不必再指定它,而类路径扫描在默认情况下是正确的。

创建你自己的切片

基于这些知识,创建您自己的切片实际上非常简单。类似切片的一个例子可能是一个新的 DataJdbcTest,类似于 DataJpaTest的切片,它只配置 JdbcTemplate,并且不使用JPA。如果您想要让代码跑起来,请查看 github repository 以了解更多细节。

我们的第一步是创建 @AutoconfigureDataJdbc

代码语言:javascript
复制
package com.example.test.autoconfigure.jdbc;

import java.lang.annotation.*;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ImportAutoConfiguration
public @interface AutoconfigureDataJdbc {
}

并注册相关的自动配置,以便在该注释出现时应用。再次,创建一个 META-INF/spring.factories 资源文件:

代码语言:javascript
复制
com.example.test.autoconfigure.jdbc.AutoconfigureDataJdbc=\
org.s.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.s.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.s.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.s.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.s.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.s.boot.autoconfigure.transaction.TransactionAutoConfiguration

一旦这个可重用的基础设施就位,您就可以创建您的测试切片,并简单地指定您需要一个数据库和jdbc:

代码语言:javascript
复制
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJdbcTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoconfigureDataJdbc
@AutoConfigureTestDatabase
@ImportAutoConfiguration
public @interface DataJdbcTest { }

DataJdbcTypeExcludeFilter确保排除所有其他服务,因为这样的测试在默认情况下不需要任何bean。它可以改进,允许将服务定义为注解的参数,就像 WebMvcTest添加指定的控制器一样。

一旦您完成了这一操作,您只需要添加注解,并且您的 JdbcTemplate就会自动为您配置一个测试数据库:

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@DataJdbcTest
public class DataJdbcSampleTests {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    ...
}

总结

Spring Boot 1.4 将自动配置带到您的测试中,并允许您轻松地编写自己的测试注解。在本文中,我们了解了 WebMvcTest 如何工作,以及如何创建自己的“jdbc”切片。我们实际上正在考虑在下一个版本中添加这个注解,所以请及时提出意见和建议!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义自动配置
  • Classpath扫描调优
  • 测试引导
  • 创建你自己的切片
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档