对Pivotal团队来说,工作上的好事情是他们拥有一个被叫做Pivotal Labs的灵活发展部门,拥有Labs团队的Lean 和 XP程序设计方法学的强大支持,例如结对编程和测试驱动开发。他们对于测试的酷爱已经对Spring Boot 1.4产生独特的影响,正如我们已经开始通过获取重大的反馈来对事物本身进行改善。这篇文章重点介绍了一些新的测试功能,这些功能刚刚使用在M2最新的版本中。

一、没有Spring的实验测试
单元测试任何Spring @Component的最简单的方式就是不要涉及到Spring的任何方面。这个方法同时也是尝试和建构代码的最好方式,所以classes可以被实例化和直接测试。通常,归结为几方面:

1、用干净的注点分离组织你的代码,以便于每个部分都可以被单元测试。TDD是一种不错的实现方式。
2、使用constructor injection(构造子注入)确保目标对象可以直接被实例化的。不要使用field injection,因为它只会让你的测试更难写。

使用Spring框架4.3会让编写组件变得很容易,就好像你不再需要使用@Autowired就可以使用constructor injections了。只要你有一个单独的构造函数,Spring会暗中将它当做一个自动配置的目标:

1
2
3
4
5
6
7
8
9
10
@Component
public class MyComponent {
     
    private final SomeService service;
 
    public MyComponent(SomeService service) {
        this.service = service;
    }
 
}

现在,测试mycomponent,就像直接创建它一样简单,调用一些方法:

1
2
3
4
5
6
@Test
public void testSomeMethod() {
    SomeService service = mock(SomeService.class);
    MyComponent component = new MyComponent(service);
    // setup mock and class component methods
}

二、Spring Boot 1.3概括
当然,你经常需要将堆栈稍微提升,开始编写包含Spring的综合测试。幸运的是,Spring框架提供spring测试模块的帮助,不幸的是,通过Spring Boot 1.3,大家有很多不同的方式来使用它。

你可能会使用@ContextConfiguration注释和SpringApplicationContextLoader的组合:

1
2
3
4
5
6
7
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=MyApp.class, loader=SpringApplicationContextLoader.class)
public class MyTest {
 
    // ...
 
}

你可能已经选择了@SpringApplicationConfiguration:

1
2
3
4
5
6
7
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(MyApp.class)
public class MyTest {
 
    // ...
 
}

你可能会通过@IntegrationTest结合其中任何一个:

1
2
3
4
5
6
7
8
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(MyApp.class)
@IntegrationTest
public class MyTest {
 
    // ...
 
}

或者是利用@WebIntegrationTest(或者可能是@IntegrationTest+ @WebAppConfiguration):

1
2
3
4
5
6
7
8
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(MyApp.class)
@WebIntegrationTest
public class MyTest {
 
    // ...
 
}

你也可以到混合随机端口上运行的服务器中(@WebIntegrationTest(randomPort=true))添加属性(使用@IntegrationTest("myprop=myvalue")或者@TestPropertySource(properties="myprop=myvalue"))。

你有很多选择可以选。

三、Spring Boot 1.4简单化
使用Spring Boot 1.4之后,事情就会变得简单多了。这里是一个用于常规测试的@SpringBootTest注释,与你应用程序中测试插件的一些特定变体一样(稍后将详细介绍)。

下面展示的是一个Spring Boot 1.4综合测试的典型案例:

1
2
3
4
5
6
7
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyTest {
 
    // ...
     
}

以下是发生了的一个故障:
1、@RunWith(SpringRunner.class) 告诉JUnit运行使用Spring的测试支持。SpringRunner是SpringJUnit4ClassRunner的新名字,这个名字只是让名字看起来简单些。

2、@SpringBootTest的意思是“带有Spring Boot支持的引导程序”(例如,加载应用程序、属性,为我们提供Spring Boot的所有精华部分)。

3、webEnvironment属性允许为测试配置特定的“网络环境”。你可以利用一个MOCK小服务程序环境开始你的测试,或者使用一个运行在RANDOM_PORT或者 DEFINED_PORT上的真正的HTTP服务器。

4、如果我们想要加载一个特定的配置,我们可以用@SpringBootTest class属性。在这个实例中,我们省略classes就意味着测试要首次尝试从任意一个inner-classes中加载@ configuration,如果这个尝试失败了,它会在你主要的@SpringBootApplicationclass中进行搜索。

特性现在都以相同的方式加载,如同Spring的常规@TestPropertySource注释。@SpringBootTest注释通常含有特性属性,这个属性可以被用来指定任何应该在环境中定义的额外特性。

这是一个更具体的例子,真正REST末端实际上的采样数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyTest {
     
    @Autowired
    private TestRestTemplate restTemplate;
 
    @Test
    public void test() {
        this.restTemplate.getForEntity(
            "/{username}/vehicle", String.class, "Phil");
    }
 
}

请注意,TestRestTemplate现在是随意使用的,就像@SpringBootTest随时都能使用bean一样。这是预配置解决http://localhost:${local.server.port}的相对路径。我们也可以使用@LocalServerPort注释注入实际的端口,这样服务器就能在测试领域上运行。

四、模仿和侦查
当你开始测试真正的系统时,你经常会发现它有助于模拟特定的beans。模仿的常见场景包括模拟服务,这个服务在你测试或者测试失败场景的时候是不可用的,因为这很难在同一个系统中触发。

使用Spring Boot 1.4你可以轻松地建造一个Mockito mocks,可以取代现有的bean,或者创建一个新的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleTestApplicationWebIntegrationTests {
 
    @Autowired
    private TestRestTemplate restTemplate;
 
    @MockBean
    private VehicleDetailsService vehicleDetailsService;
 
    @Before
    public void setup() {
        given(this.vehicleDetailsService.
            getVehicleDetails("123")
        ).willReturn(
            new VehicleDetails("Honda", "Civic"));
    }
 
    @Test
    public void test() {
        this.restTemplate.getForEntity("/{username}/vehicle",
            String.class, "sframework");
    }
 
}

以下是一些例子:

1、为VehicleDetailsService创建一个 Mockito mock。
2、将它如同bean一样注入ApplicationContext。
3、将它注入到在测试领域。
4、在·设置方法上存根。
5、触发最终会调用mock的东西。

测试模拟将自动重置。它们还会形成一部分Spring Test使用的缓存键(所以,没有必要添加@DirtiesContext)。

Spies以类似的方式工作。用@SpyBean简单地注释一个测试领域来让spy隐藏所有ApplicationContext中现有的bean。

五、JSON断言

如果你使用spring-boot-starter-test POM来导入测试依赖关系,从1.4开始,你将有很好的AssertJ文库。AssertJ 提供了一个流畅的assertion API 来代替JUnit的基础org.junit.Assert class。如果你之前没有遇到过,哪买看下面的实例,一个基础的AssertJcall看起来就是这样的:

1
assertThat(library.getName()).startsWith("Spring").endsWith("Boot");

Spring Boot 1.4 提供了扩展的断言,这样你就能用它来检查JSON marshalling 和 unmarshalling。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class VehicleDetailsJsonTests {
 
    private JacksonTester<VehicleDetails> json;
 
    @Before
    public void setup() {
        ObjectMapper objectMappper = new ObjectMappper();
        // Possibly configure the mapper
        JacksonTester.initFields(this, objectMappper);
    }
 
    @Test
    public void serializeJson() {
        VehicleDetails details =
            new VehicleDetails("Honda", "Civic");
 
        assertThat(this.json.write(details))
            .isEqualToJson("vehicledetails.json");
 
        assertThat(this.json.write(details))
            .hasJsonPathStringValue("@.make");
 
        assertThat(this.json.write(details))
            .extractingJsonPathStringValue("@.make")
            .isEqualTo("Honda");
    }
 
    @Test
    public void deserializeJson() {
        String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
 
        assertThat(this.json.parse(content))
            .isEqualTo(new VehicleDetails("Ford", "Focus"));
 
        assertThat(this.json.parseObject(content).getMake())
            .isEqualTo("Ford");
    }
 
}

JSON的比较实际上是使用JSONassert执行的,所以只有JSON的逻辑结构需要匹配。您还可以在上面的示例中看到,JsonPath表达式是如何用于测试或提取数据中的。

六、测试应用程序插件
Spring Boot的自动配置功能对配置应用程序所需要运行的一切是很有用的。不幸的是,完整的自动配置有时候对于自动测试来说有点多余。有时候你只是想为应用程序配置一个“插件”——Jackson配置正确吗?我的MVC控制器返回正确的状态代码吗?我的JPA查询运行吗?

使用Spring Boot 1.4这些常见的场景现在很容易被测试。我们也能很容易构建自己的注释,这个注释仅应用了你需要的自动配置classes。

七、测试JPA插件
测试您应用程序的JPA插件(Hibernate +Spring数据)可以使用@DataJpaTest注释。@DataJpaTest将会这样:

1、配置一个内存数据库。
2、自动配置Hibernate,Spring数据和数据源。
3、执行@EntityScan。
4、打开SQL日志记录。

以下是一个典型的测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryTests {
 
    @Autowired
    private TestEntityManager entityManager;
 
    @Autowired
    private UserRepository repository;
 
    @Test
    public void findByUsernameShouldReturnUser() {
        this.entityManager.persist(new User("sboot", "123"));
        User user = this.repository.findByUsername("sboot");
         
        assertThat(user.getUsername()).isEqualTo("sboot");
        assertThat(user.getVin()).isEqualTo("123");
    }
 
}

以上实验中的TestEntityManager是由Spring Boot支持的。一个标准JPA EntityManager选择所提供的方法通常会在编写测试的过程中使用。

八、测试Spring MVC插件
你可以使用@WebMvcTest注解来测试应用程序的Spring MVC插件。像这样:

1、自动配置Spring MVC、Jackson,Gson,消息转换器等。
2、加载相关的组件(@Controller, @RestController, @JsonComponent等)。
3、配置MockMVC。

下面是一个测试单个控制器的典型实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class UserVehicleControllerTests {
 
    @Autowired
    private MockMvc mvc;
 
    @MockBean
    private UserVehicleService userVehicleService;
 
    @Test
    public void getVehicleShouldReturnMakeAndModel() {
        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"));
    }
 
}

如果你偏爱HtmlUnit,你可以是用WebClient 来代替 MockMvc。如果你更喜欢selenium,你可以切换到WebDriver。

九、测试JSON插件
如果你需要测试JSON 序列化是否如预期般运营,你可以使用 @JsonTest。像这样:

1、自动配置Jackson和/或Gson。
2、添加你可以定义的任一模块或者 @JsonComonent beans。
3、触发任何JacksonTester或GsonTester字段的初始化。

以下是实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RunWith(SpringRunner.class)
@JsonTest
public class VehicleDetailsJsonTests {
 
    private JacksonTester<VehicleDetails> json;
 
    @Test
    public void serializeJson() {
        VehicleDetails details = new VehicleDetails(
            "Honda", "Civic");
 
        assertThat(this.json.write(details))
            .extractingJsonPathStringValue("@.make")
            .isEqualTo("Honda");
    }
 
}

总结
如果你想尝试Spring Boot 1.4中新的测试特性,你可以从http://repo.spring.io/snapshot/上抓取M2。还有一个GitHub上的示例项目以及更新的文档可以用。如果你有任何我们应该支持的,关于添加“插件”的建议或者改进,请提出及时提出。

Spring Boot 1.4测试的改进的更多相关文章

  1. spring boot项目如何测试,如何部署

    有很多网友会时不时的问我,spring boot项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下spring boot 如何开发.调试.打包到最后的投产上线. 开发阶段 单元 ...

  2. Spring Boot应用的测试——Mockito

    Spring Boot应用的测试——Mockito Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试:生成测试数据初始化数据库用于测试:Spring ...

  3. Spring Boot中的测试

    文章目录 简介 添加maven依赖 Repository测试 Service测试 测试Controller @SpringBootTest的集成测试 Spring Boot中的测试 简介 本篇文章我们 ...

  4. 如何使用Dubbo 2.7.0和Spring boot实现FAT测试(Feature Acceptance Test)

    在一个调用链非常长的功能中,如果想修改其中的一个特性,并进行测试,而又不影响该环境的其他用户使用现有功能.特性,例如: 1. A.B.C.D之间通过Dubbo实现远程调用 2. 这些模块可能有一个或者 ...

  5. Spring Boot 1.4测试的简单理解

    首先maven要引入spring-boot-starter-test这个包. 先看一段代码 @RunWith(SpringRunner.class) @SpringBootTest(webEnviro ...

  6. Spring Boot 解决方案 - JUnit 测试

    简单的 JUnit 项目 回顾一下创建并运行简单的 JUnit 测试项目,先添加 JUnit 依赖然后编写类似如下模板的测试类,使用 IDE 的话直接用插件运行就行, 使用 Maven 的话运行命令 ...

  7. 【星云测试】开发者测试-采用精准测试工具对Spring Boot应用进行测试

    简介:本文主要介绍把现今主流的springboot框架项目和精准测试工具进行结合和应用,通过精准测试的数据穿透.数据采集.测试用例与代码的双向追溯.数据分析等一系列精准测试的特有功能,达到对项目质量的 ...

  8. Spring、Spring Boot和TestNG测试指南 - 使用Spring Boot Testing工具

    Github地址 前面一个部分讲解了如何使用Spring Testing工具来测试Spring项目,现在我们讲解如何使用Spring Boot Testing工具来测试Spring Boot项目. 在 ...

  9. spring boot 单元测试 --- 在测试类使用 javabean注解操作接口

    1.依赖包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>s ...

随机推荐

  1. R︱Linux+Rstudio Server尝鲜笔记(打造最佳Rstudio体验+报错的解决方案)

    Rstudio Server 是Rstudio开发的基于R语言的网页版(只能在Linux),你在手机上都可以运行R,还是挺方便的.就是配置起来有点麻烦.      官方下载链接:https://www ...

  2. DirectShow使用说明

    1) 安装directX sdk 2)打开安装目录下的dshow.dsw,进行编译 3)在VC++的Tools/Option/Directory的Include和Library中分别加入 C:/DXS ...

  3. Srtuts2实现登录界面(不连接数据库)报错(三)

    二月 28, 2014 11:41:20 下午 org.apache.catalina.core.AprLifecycleListener init 严重: An incompatible versi ...

  4. (五)java运算

    java在运算的时候,会存在数据类型的转换,其中一种是自动类型转换,也称为隐式类型转换,这种转换需要满足一定的条件:     1.这两种类型是兼容的,例如同时都是整数类型或者都是数字类型     2. ...

  5. java 后台封装json数据学习总结(一)

    一.数据封装 1. List集合转换成json代码 List list = new ArrayList(); list.add( "first" ); list.add( &quo ...

  6. OpenStack_I版 4.Dashboard部署

    由python的DjangoWeb框架开发的   使用keystone默认的角色来访问各种服务   Dashboard安装       Dashboard是openstack的Web管理界面,需要将它 ...

  7. 二叉树与AVL树

    二叉树 什么是二叉树? 父节点至多只有两个子树的树形结构成为二叉树.如下图所示,图1不是二叉树,图2是一棵二叉树. 图1 普通的树                                    ...

  8. word文档的动态添加数据

    解释:其实主要的思路就是先把word文档转化成xml格式的数据,然后在把xml格式的数据转化成字节流让程序来读取,最后在把字节流转化成xml格式的数据,然后在转化成word文档. poi工具也是这个思 ...

  9. Java汉字乱码问题

    window->preferences->输入框输入"encod" 将text file encoding 从default改成other utf-8 同理,css,H ...

  10. 【CJOJ P2110】YL杯超级篮球赛

    [CJOJ P2110]YL杯超级篮球赛 Description 一年一度的高一YL杯超级篮球赛开赛了.当然,所谓超级的意思是参赛人数可能多于5人.小三对这场篮球赛非常感兴趣,所以一场都没有落下.每天 ...