zoukankan      html  css  js  c++  java
  • SpringBootTest单元测试及日志

    springboot系列学习笔记全部文章请移步值博主专栏**: spring boot 2.X/spring cloud Greenwich
    由于是一系列文章,所以后面的文章可能会使用到前面文章的项目。springboot系列代码全部上传至GitHub:https://github.com/liubenlong/springboot2_demo
    本系列环境:Java11;springboot 2.1.1.RELEASE;springcloud Greenwich.RELEASE;MySQL 8.0.5;

    单元测试和日志比较简单,放到一起讲一下。本篇文章需要使用到Junit、TestNg、Mockito、Spring Testing,本文不会对其使用进行特别详细的说明,请自行检索

    日志

    springboot官方文档中指出,如果我们使用Starters,那么默认使用Logback作为日志输出组件。当然还支持Commons Logging, Log4J等组件。

    简单日志配置(包含了指定文件目录, 格式,以及level):

    logging:
      level:
        root: info
        com.example.controller: info
        com.example.service: warn
      file: d://a.log
      pattern:
        console: "%d - %msg%n"
    

    springboot中提供的日志的配置参数

    # ----------------------------------------
    # CORE PROPERTIES
    # ----------------------------------------
    debug=false # Enable debug logs.
    trace=false # Enable trace logs.
    

    LOGGING

    logging.config= # Location of the logging configuration file. For instance, classpath:logback.xml for Logback.
    logging.exception-conversion-word=%wEx # Conversion word used when logging exceptions.
    logging.file= # Log file name (for instance, myapp.log). Names can be an exact location or relative to the current directory.
    logging.file.max-history=0 # Maximum of archive log files to keep. Only supported with the default logback setup.
    logging.file.max-size=10MB # Maximum log file size. Only supported with the default logback setup.
    logging.group.= # Log groups to quickly change multiple loggers at the same time. For instance, logging.level.db=org.hibernate,org.springframework.jdbc.
    logging.level.
    = # Log levels severity mapping. For instance, logging.level.org.springframework=DEBUG.
    logging.path= # Location of the log file. For instance, /var/log.
    logging.pattern.console= # Appender pattern for output to the console. Supported only with the default Logback setup.
    logging.pattern.dateformat=yyyy-MM-dd HH:mm:ss.SSS # Appender pattern for log date format. Supported only with the default Logback setup.
    logging.pattern.file= # Appender pattern for output to a file. Supported only with the default Logback setup.
    logging.pattern.level=%5p # Appender pattern for log level. Supported only with the default Logback setup.
    logging.register-shutdown-hook=false # Register a shutdown hook for the logging system when it is initialized.

    通常只需要在applicatiom.yml中配置即可,但是如果想要对日志进行更加复杂纤细的配置,可能就需要使用到对应日志系统的配置文件了。如果使用logbak,我们只需要在resource中添加logback.xml文件即可(当然下面只是简单实例,详细的logbak的xml配置请读者自行配置):

    <?xml version="1.0" encoding="GBK"?>
    <configuration debug="false">
        <appender name="CONSOLE"
                  class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <charset>UTF-8</charset>
                <pattern>
                    %d %-4relative [%thread] %-5level %logger{36} [T:%X{trans}]  - %msg%n
                </pattern>
            </encoder>
        </appender>
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logs/demo.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>logs/demo.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
                <maxHistory>10</maxHistory>
                <maxFileSize>200MB</maxFileSize>
                <totalSizeCap>10GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] %level %logger{35} [T:%X{trans}] %msg%n</pattern>
            </encoder>
        </appender>
    
    <span class="token tag"><span class="token tag"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">&lt;</span></span></span></span></span><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">root</span></span></span></span></span></span></span></span></span><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"> </span></span></span></span><span class="token attr-name"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">level</span></span></span></span></span></span></span></span></span><span class="token attr-value"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">=</span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"</span></span></span></span></span></span></span></span></span><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">INFO</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"</span></span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">&gt;</span></span></span></span></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">&lt;</span></span></span></span></span><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">appender-ref</span></span></span></span></span></span></span></span></span><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"> </span></span></span></span><span class="token attr-name"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">ref</span></span></span></span></span></span></span></span></span><span class="token attr-value"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">=</span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"</span></span></span></span></span></span></span></span></span><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">FILE</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"</span></span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">/&gt;</span></span></span></span></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">&lt;</span></span></span></span></span><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">appender-ref</span></span></span></span></span></span></span></span></span><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"> </span></span></span></span><span class="token attr-name"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">ref</span></span></span></span></span></span></span></span></span><span class="token attr-value"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">=</span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"</span></span></span></span></span></span></span></span></span><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">CONSOLE</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"</span></span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">/&gt;</span></span></span></span></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">&lt;/</span></span></span></span></span><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">root</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag"><span class="hljs-tag">&gt;</span></span></span></span></span></span>
    

    </configuration>

    @Slf4j

    为了方便的使用日志,可以借助spring的@slf4j注解,可以自动注入log,代码中可以直接使用,比较方便:

    @RestController
    @Slf4j
    public class HelloController {
        @Autowired
        private Stu stu;
        @Autowired
        private Person person;
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@GetMapping</span></span></span></span></span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"/properties1"</span></span></span></span></span><span class="token punctuation">)</span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> String </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">properties1</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"com.example.controller.HelloController.properties1 执行"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"stu={}"</span></span></span></span></span><span class="token punctuation">,</span> stu<span class="token punctuation">)</span><span class="token punctuation">;</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"person={}"</span></span></span></span></span><span class="token punctuation">,</span> person<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"Welcome to springboot2 world ~"</span></span></span></span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//省略代码</span></span></span></span></span>
    

    单元测试

    一个Spring Boot application 是Spring ApplicationContext, 在单元测试时没有什么特殊的。
    当你使用SpringApplication 时,外部属性,日志等其他功能会被默认装配

    springboot提供了@SpringBootTest注解来辅助我们进行测试。

    需要注意:如果我们使用的是JUnit 4 ,那么需要添加@RunWith(SpringRunner.class)否则所有注解将会被忽略。
    如果你使用的是JUnit5 ,那么在 SpringBootTest 上没有必要添加 @ExtendWith,因为@…Test已经添加了ExtendWith

    If you are using JUnit 4, don’t forget to also add @RunWith(SpringRunner.class) to your test, otherwise the annotations will be 
    ignored. If you are using JUnit 5, there’s no need to add the equivalent @ExtendWith(SpringExtension) as @SpringBootTest and the 
    other @…Test annotations are already annotated with it.
    

    简单实例

    引入test的starter依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    

    在src/test/java目录下创建MyTest.java

    
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {Application.class})// 指定启动类
    @Slf4j
    public class MyTests {
        @Autowired
        private Person person;
        @Autowired
        private HelloService helloService;
    
    <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">/**
     * 使用断言
     */</span></span></span></span></span>
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">test2</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"test hello 2"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        TestCase<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span></span><span class="token punctuation">,</span> <span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    
    <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">/**
     * 测试注入
     */</span></span></span></span></span>
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">test3</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"person={}"</span></span></span></span></span><span class="token punctuation">,</span> person<span class="token punctuation">)</span><span class="token punctuation">;</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"helloService.getVal()={}"</span></span></span></span></span><span class="token punctuation">,</span> helloService<span class="token punctuation">.</span><span class="token function">getVal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Before</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">testBefore</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"before"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@After</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">testAfter</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"after"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    我们这里单独执行test3,他会向正常启动springboot服务一样,注入相关的bean,输出如下:
    在这里插入图片描述

    @TestConfiguration

    @TestConfiguration是Spring Boot Test提供的一种工具,用它我们可以在一般的@Configuration之外补充测试专门用的Bean或者自定义的配置。

    我们看@TestConfiguration的定义

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    @TestComponent
    public @interface TestConfiguration {
    //省略
    

    可见真正起作用的是@TestComponent:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface TestComponent {
    //省略
    

    @TestComponent 用于声明专门用于测试的bean , 他不应该被自动扫描到。也就是说如果你使用@ComponentScan来扫描bean,那么需要将其排除在外:

    @ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      ...})
    

    由于@SpringBootApplication已经添加有排除TypeExcludeFilter的功能,固使用@SpringBootApplication时不会加载@TestComponent声明的bean:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = {
            @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    

    @TestConfiguration 应用实例

    编写一个bean的创建类:

    package config;
    

    import com.example.pojo.Foo;
    import org.springframework.boot.test.context.TestConfiguration;
    import org.springframework.context.annotation.Bean;

    @TestConfiguration
    public class Config {

    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Bean</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> Foo </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">foo</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span></span> <span class="token class-name">Foo</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"from config"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    Foo.java:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Foo {
        private String name;
    }
    

    编写测试类(IDEA 可能会在foo属性上标红提示错误,不用管,IDE还没有那么智能,识别不了这里的自动注入):

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {Application.class})// 指定启动类
    @Import(Config.class)
    @Slf4j
    public class TestConfiguration1 {
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Autowired</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">private</span></span></span></span></span> Foo foo<span class="token punctuation">;</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">testPlusCount</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"TestConfiguration1"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Assert<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span>foo<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"from config"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    执行这里的testPlusCount方法,测试通过。
    当然上面Config中的注解@TestConfiguration可以换成@Configuration效果也是一样的,@TestConfiguration是专门用于测试的。

    使用mock方式对controller进行单元测试(无需运行web服务)

    默认情况下,使用@SpringBootTest不会真正启动web服务,当我们测试controller时,spring测试提供了MockMvc供我们方便的测试controller,就像从浏览器发起请求一样。
    在HelloController中有这么一个方法:

    @GetMapping("/hello")
    public String hello() {
        return "Welcome to springboot2 world ~";
    }
    

    启动服务在浏览器中访问:
    在这里插入图片描述

    关闭tomcat服务,我们看如何进行单元测试。

    import com.example.Application;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.servlet.MockMvc;
    

    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {Application.class})// 指定启动类
    @AutoConfigureMockMvc
    public class MockMvcExampleTests {
    @Autowired
    private MockMvc mvc;

    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">exampleTest</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> Exception </span></span></span></span><span class="token punctuation">{</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>mvc<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"/hello"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">content</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"Welcome to springboot2 world ~"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andDo</span><span class="token punctuation">(</span>MockMvcResultHandlers<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    tomcat服务已经关闭,执行单元测试,输出结果:

    
    2018-12-30 19:29:29.971  INFO 15100 --- [           main] MockMvcExampleTests                      : Starting MockMvcExampleTests on HIH-D-20265 with PID 15100 (started by hzliubenlong in D:workspace-wyspringboot2demo)
    2018-12-30 19:29:29.973  INFO 15100 --- [           main] MockMvcExampleTests                      : No active profile set, falling back to default profiles: default
    2018-12-30 19:29:31.419  INFO 15100 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
    2018-12-30 19:29:31.620  INFO 15100 --- [           main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
    2018-12-30 19:29:31.624  INFO 15100 --- [           main] o.s.t.web.servlet.TestDispatcherServlet  : Initializing Servlet ''
    2018-12-30 19:29:31.633  INFO 15100 --- [           main] o.s.t.web.servlet.TestDispatcherServlet  : Completed initialization in 9 ms
    2018-12-30 19:29:31.651  INFO 15100 --- [           main] MockMvcExampleTests                      : Started MockMvcExampleTests in 2.201 seconds (JVM running for 2.974)
    

    MockHttpServletRequest:
    HTTP Method = GET
    Request URI = /hello
    Parameters = {}
    Headers = {}
    Body = null
    Session Attrs = {}

    Handler:
    Type = com.example.controller.HelloController
    Method = public java.lang.String com.example.controller.HelloController.hello()

    Async:
    Async started = false
    Async result = null

    Resolved Exception:
    Type = null

    ModelAndView:
    View name = null
    View = null
    Model = null

    FlashMap:
    Attributes = null

    MockHttpServletResponse:
    Status = 200
    Error message = null
    Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[30]}
    Content type = text/plain;charset=UTF-8
    Body = Welcome to springboot2 world ~
    Forwarded URL = null
    Redirected URL = null
    Cookies = []
    2018-12-30 19:29:31.916 INFO 15100 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'

    其中中间的内容为打印的请求详细信息,该测试通过。

    使用mock方式对controller进行单元测试(无需运行web服务)

    如果您需要启动运行web服务,我们建议您使用随机端口。 如果您使用的是@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT),则可以随机进行测试运行。

    这里允许自动注入TestRestTemplate:

    import com.example.Application;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
    import org.springframework.boot.test.web.client.TestRestTemplate;
    import org.springframework.test.context.junit4.SpringRunner;
    

    import static org.assertj.core.api.Assertions.assertThat;

    /**

    • 测试基于普通springmvc的运行的controller服务
      */
      @RunWith(SpringRunner.class)
      //使用随机端口
      @SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
      public class RandomPortTestRestTemplateExampleTests {

      @Autowired
      private TestRestTemplate restTemplate;

      @Test
      public void exampleTest() {
      String body = this.restTemplate.getForObject("/hello", String.class);
      assertThat(body).isEqualTo("Welcome to springboot2 world ~");
      }
      }

    首先启动该springboot应用,然后执行这个单元测试。

    使用mock方式对controller进行单元测试(需运行web服务且 使用webflux

    具体的webflux相关的内容后续会讲。这里只需要知道这个springboot提供的是基于reactor的响应式编程(异步非阻塞)架构就行了。而我们之前使用的基于Tomcat的servlet3.1之前的springmvc是同步阻塞的。

    要想使用webflux,需要更换spring-boot-starter-webspring-boot-starter-webflux

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    

    编写测试代码

    import com.example.Application;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.reactive.server.WebTestClient;
    

    @RunWith(SpringRunner.class)
    //指定使用随机端口(官网推荐的,原因待验证)
    @SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
    public class RandomPortWebTestClientExampleTests {
    /**
    *WebTestClient 是用于测试web服务器的非阻塞的响应式客户端
    */

    @Autowired
    private WebTestClient webClient;

    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">exampleTest</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>webClient<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">uri</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"/hello"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">exchange</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">expectStatus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">expectBody</span><span class="token punctuation">(</span>String<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEqualTo</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"Welcome to springboot2 world ~"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    首先启动该springboot应用,然后执行这个单元测试。

    改为webflux的starter以后,观察启动日志,可以发现不再是基于Tomcat,而是基于netty了Netty started on port(s): 8080

    @MockBean 对bean进行mock测试

    在实际项目中,有一些bean可能会调用第三方,依赖外部组件或项目。但是我们单元测试不需要真正调用。那么我们可以使用@MockBean进行mock结果。
    假设HelloService中有调用外部服务的方法:

    public interface HelloService {
    
    <span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function">String </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getVal</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="token punctuation">;</span>
    
    <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//模拟远程调用,或者其他服务调用</span></span></span></span></span>
    <span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function">String </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getRemoteVal</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="token punctuation">;</span>
    

    }

    @Component
    @Slf4j
    public class HelloServiceImpl implements HelloService{

    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> String </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getVal</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="token punctuation">{</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"haha"</span></span></span></span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//模拟远程调用,或者其他服务调用</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> String </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getRemoteVal</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="token punctuation">{</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"真正发起外部请求"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"remote Val"</span></span></span></span></span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    编写单元测试代码:

    import com.example.Application;
    import com.example.service.HelloService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.test.context.junit4.SpringRunner;
    

    import static org.assertj.core.api.Assertions.assertThat;
    import static org.mockito.BDDMockito.given;

    /**

    • 测试bean结果的mock
      */
      @RunWith(SpringRunner.class)
      @SpringBootTest(classes = {Application.class})// 指定启动类
      public class MockBeanTest {
      @MockBean //这里使用 @SpyBean 是同样效果
      private HelloService helloService;
      @Test
      public void exampleTest() {
      //这句的意思是当调用helloService的getRemoteVal方法时,返回mock的结果:"远程调用结果"
      given(this.helloService.getRemoteVal()).willReturn("远程调用结果");

       <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//进行调用测试</span></span></span></span></span>
       String reverse <span class="token operator">=</span> helloService<span class="token punctuation">.</span><span class="token function">getRemoteVal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token function">assertThat</span><span class="token punctuation">(</span>reverse<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEqualTo</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"远程调用结果"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      

      }
      }

    执行单元测试,可以发现并没有真正发起请求。

    更多测试相关内容请参见官网 Testing

    测试json @JsonTest

    import static org.assertj.core.api.Assertions.assertThat;
    

    @RunWith(SpringRunner.class)
    //这里不能使用@SpringBootTest否则报错:Configuration error: found multiple declarations of @BootstrapWith for test class [MyJsonTests]
    @ContextConfiguration(classes = {Application.class})
    @JsonTest
    public class MyJsonTests extends AbstractTestNGSpringContextTests {

    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Autowired</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">private</span></span></span></span></span> JacksonTester<span class="token generics function"><span class="token punctuation">&lt;</span>Stu<span class="token punctuation">&gt;</span></span> json<span class="token punctuation">;</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">testSerialize</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> Exception </span></span></span></span><span class="token punctuation">{</span>
        Stu details <span class="token operator">=</span> <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span></span> <span class="token class-name">Stu</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"马云"</span></span></span></span></span><span class="token punctuation">,</span> <span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">51</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// Assert against a `.json` file in the same package as the test</span></span></span></span></span>
        <span class="token function">assertThat</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>json<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEqualToJson</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"expected.json"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">// 或者使用基于JSON path的校验</span></span></span></span></span>
        <span class="token function">assertThat</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>json<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">hasJsonPathStringValue</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"@.name"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertThat</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>json<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>details<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">extractingJsonPathStringValue</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"@.name"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEqualTo</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"马云"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">testDeserialize</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> Exception </span></span></span></span><span class="token punctuation">{</span>
        String content <span class="token operator">=</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"{"name":"2","age":"11"}"</span></span></span></span></span><span class="token punctuation">;</span>
        <span class="token function">assertThat</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>json<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEqualTo</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span></span> <span class="token class-name">Stu</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"2"</span></span></span></span></span><span class="token punctuation">,</span> <span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">11</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertThat</span><span class="token punctuation">(</span><span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>json<span class="token punctuation">.</span><span class="token function">parseObject</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEqualTo</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"2"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    这里不能使用@SpringBootTest否则报错:Configuration error: found multiple declarations of @BootstrapWith for test class [MyJsonTests]

    有时候我们会自定义序列化风格,这里对@JsonComponent进行测试:

    @JsonComponent
    public class FooJsonComponent {
    
    <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">public</span></span></span></span></span> <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">static</span></span></span></span></span> <span class="token keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span></span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token class-name"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">Serializer</span></span></span></span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">extends</span></span></span></span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token class-name"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">JsonSerializer</span></span></span></span></span></span></span></span></span><span class="token generics function"><span class="token punctuation"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class">&lt;</span></span></span></span></span><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">Stu</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class">&gt;</span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token punctuation">{</span>
        <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Override</span></span></span></span></span>
        <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">serialize</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">Stu value</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">,</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"> JsonGenerator gen</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">,</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"> SerializerProvider serializers</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function">
                </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> IOException</span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function">,</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> JsonProcessingException </span></span></span></span><span class="token punctuation">{</span>
            gen<span class="token punctuation">.</span><span class="token function">writeString</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"name="</span></span></span></span></span> <span class="token operator">+</span> value<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">",age="</span></span></span></span></span> <span class="token operator">+</span> value<span class="token punctuation">.</span><span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    
    <span class="token punctuation">}</span>
    
    <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">public</span></span></span></span></span> <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">static</span></span></span></span></span> <span class="token keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span></span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token class-name"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">Deserializer</span></span></span></span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">extends</span></span></span></span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token class-name"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">JsonDeserializer</span></span></span></span></span></span></span></span></span><span class="token generics function"><span class="token punctuation"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class">&lt;</span></span></span></span></span><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">Stu</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class">&gt;</span></span></span></span></span></span><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"><span class="hljs-class"> </span></span></span></span><span class="token punctuation">{</span>
    
        <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Override</span></span></span></span></span>
        <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> Stu </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">deserialize</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">JsonParser p</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">,</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"> DeserializationContext ctxt</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> IOException</span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function">,</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> JsonProcessingException </span></span></span></span><span class="token punctuation">{</span>
            JsonToken t <span class="token operator">=</span> p<span class="token punctuation">.</span><span class="token function">getCurrentToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
            <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">if</span></span></span></span></span> <span class="token punctuation">(</span>t <span class="token operator">==</span> JsonToken<span class="token punctuation">.</span>VALUE_STRING<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                String trim <span class="token operator">=</span> p<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
                String<span class="token punctuation">[</span><span class="token punctuation">]</span> split <span class="token operator">=</span> trim<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">","</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                Stu stu <span class="token operator">=</span> <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">new</span></span></span></span></span> <span class="token class-name">Stu</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                stu<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span>split<span class="token punctuation">[</span><span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">0</span></span></span></span></span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"="</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span></span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                stu<span class="token punctuation">.</span><span class="token function">setAge</span><span class="token punctuation">(</span>Integer<span class="token punctuation">.</span><span class="token function">parseInt</span><span class="token punctuation">(</span>split<span class="token punctuation">[</span><span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span></span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"="</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">1</span></span></span></span></span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> stu<span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
    
            <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> <span class="token punctuation">(</span>Stu<span class="token punctuation">)</span> ctxt<span class="token punctuation">.</span><span class="token function">handleUnexpectedToken</span><span class="token punctuation">(</span><span class="token function">handledType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    

    }

    /**

    • 测试自定义的@JsonComponent
      */

      @ContextConfiguration(classes = {JsonComponentJacksonTest.class, FooJsonComponent.class})
      @JsonTest
      public class JsonComponentJacksonTest extends AbstractTestNGSpringContextTests {

      @Autowired
      private JacksonTester<Stu> json;

      @Test
      public void testSerialize() throws Exception {
      Stu details = new Stu("zhangsan", 12);
      assertThat(this.json.write(details).getJson()).isEqualTo(""name=zhangsan,age=12"");
      }

      @Test
      public void testDeserialize() throws Exception {
      String content = ""name=zhangsan,age=13"";
      Stu actual = this.json.parseObject(content);
      assertThat(actual).isEqualTo(new Stu("zhangsan", 13));
      assertThat(actual.getName()).isEqualTo("zhangsan");
      assertThat(actual.getAge()).isEqualTo(13);
      }
      }

    @TestPropertySource 对属性配置进行mock

    使用springboot我们通常会将配置设置在application.yml中,但是在测试的时候,可能会对某些配置的值进行修改,接下来我们使用@TestPropertySource来实现这个功能。

    使用spring提供的@PropertySource

    springboot提供的@ConfigurationProperties可以加载application.yml中的配置,如果你的配置放到其他目录或者叫其他名称,可以使用@PropertySource来进行加载。

    我们在resources目录下创建两个配置文件:
    在这里插入图片描述
    property-source.properties文件内容是lastName=wanganshi。property-source.yml内容是lastName: libai@PropertySource可以支持properties和yml两种格式。
    编写类PropertySourceConfig.java来加载配置文件中的内容

    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    

    @Configuration
    //支持properties和yml
    //@PropertySource("classpath:property-source.properties")
    @PropertySource("classpath:property-source.yml")
    public class PropertySourceConfig {
    }

    编写测试类:

    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.EnvironmentAware;
    import org.springframework.core.env.ConfigurableEnvironment;
    import org.springframework.core.env.Environment;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.TestPropertySource;
    import org.springframework.test.context.junit4.SpringRunner;
    

    import java.util.Map;

    import static java.util.stream.Collectors.toList;

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    @ContextConfiguration(classes = PropertySourceConfig.class) //加载属性配置
    @TestPropertySource( // 对属性进行设置
    properties = {"lastName=abc", "bar=uvw"}
    )
    public class PropertySourceTest1 implements EnvironmentAware {

    <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">private</span></span></span></span></span> Environment environment<span class="token punctuation">;</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">test1</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        Assert<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span>environment<span class="token punctuation">.</span><span class="token function">getProperty</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"lastName"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"abc"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Override</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">setEnvironment</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">Environment environment</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span></span></span><span class="token punctuation">.</span>environment <span class="token operator">=</span> environment<span class="token punctuation">;</span>
        Map<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">&gt;</span></span> systemEnvironment <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>ConfigurableEnvironment<span class="token punctuation">)</span> environment<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getSystemEnvironment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"=== System Environment ==="</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token function">getMapString</span><span class="token punctuation">(</span>systemEnvironment<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"=== Java System Properties ==="</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Map<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">&gt;</span></span> systemProperties <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>ConfigurableEnvironment<span class="token punctuation">)</span> environment<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getSystemProperties</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token function">getMapString</span><span class="token punctuation">(</span>systemProperties<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">private</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> String </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getMapString</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">Map</span></span></span></span></span></span></span></span><span class="token generics function"><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">&lt;</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">String</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">,</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"> Object</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">&gt;</span></span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"> map</span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">return</span></span></span></span></span> String<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"
    "</span></span></span></span></span><span class="token punctuation">,</span>
                map<span class="token punctuation">.</span><span class="token function">keySet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>k <span class="token operator">-</span><span class="token operator">&gt;</span> k <span class="token operator">+</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"="</span></span></span></span></span> <span class="token operator">+</span> map<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>k<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span><span class="token function">toList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    测试通过。大家可以将@TestPropertySource注解去掉来观察输出结果。

    对springboot提供的类型安全的属性配置进行mock

    前面已经讲过如何进行类型安全的属性配置。这种情况依然可以使用@TestPropertySource对属性进行mock:
    我们使用spring boot 2.1学习笔记【四】属性配置的Person类进行测试。
    直接编写测试类:

    import com.example.Application;
    import com.example.pojo.Person;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.TestPropertySource;
    import org.springframework.test.context.junit4.SpringRunner;
    

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {Application.class})// 指定启动类
    @Slf4j
    @TestPropertySource(
    properties = {"person.lastName=张飞", "person.age=49"}
    )
    public class PropertySourceTest {
    @Autowired
    private Person person;

    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">test1</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span>person<span class="token punctuation">.</span><span class="token function">getLastName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Assert<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span>person<span class="token punctuation">.</span><span class="token function">getLastName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"张飞"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    

    }

    测试结果通过,大家可以将@TestPropertySource注解去电观察运行结果。

    为单元测试单独提供测试配置

    就像上图中那样,我们在src/test/resources目录下创建一个单元测试专用的属性配置文件。就可以在@TestPropertySource指定加载这个配置即可。
    test-property-source.yml文件内容:

    testp: 123456789
    person:
      lastName: abc
    

    PropertySourceTest1进行改造:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    @ContextConfiguration(classes = PropertySourceConfig.class) //加载属性配置
    @TestPropertySource( // 对属性进行设置
            properties = {"bar=uvw"},
            locations = "classpath:test-property-source.yml"
    )
    public class PropertySourceTest1 implements EnvironmentAware {
    
    <span class="token keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-keyword">private</span></span></span></span></span> Environment environment<span class="token punctuation">;</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Value</span></span></span></span></span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"${testp}"</span></span></span></span></span><span class="token punctuation">)</span>
    String testp<span class="token punctuation">;</span>
    
    <span class="token annotation punctuation"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta"><span class="hljs-meta">@Test</span></span></span></span></span>
    <span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token function"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">test1</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span></span></span></span></span></span></span></span><span class="token punctuation"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">)</span></span></span></span></span></span></span></span></span><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"><span class="hljs-function"> </span></span></span></span><span class="token punctuation">{</span>
        Assert<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span>environment<span class="token punctuation">.</span><span class="token function">getProperty</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"lastName"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"abc"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Assert<span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span>testp<span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"123456789"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//省略部分代码</span></span></span></span></span>
    

    }

    对AOP进行测试

    我们这里对HelloService使用AspectJ进行AOP代理:

    /**
     * AOP
     */
    @Component
    @Aspect
    public class HelloAspect {
      @Pointcut("execution(* com.example.service.HelloService.getVal())")
      public void pointcut() {
      }
      @Around("pointcut()")
      public String changeGetVal(ProceedingJoinPoint pjp) {
        return "aopResult";//简单起见,这里直接模拟一个返回值了
      }
    }
    

    使用springboot进行配置,启用AOP

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = true)//启用aop
    @ComponentScan("com.example.service")
    public class AopConfig {
    }
    

    我们队MockMvcExampleTests添加一个测试方法,验证一下结果:

    @Test
    public void exampleTest1() throws Exception {
       this.mvc.perform(get("/hello1")).andExpect(status().isOk())
               .andExpect(content().string("aopResult"))
               .andDo(MockMvcResultHandlers.print());
    }
    

    测试通过,说明代理成功。接下来我们通过另一种方式直接对AOP进行测试,注释已经在代码中写清楚了:

    //省略部分import
    import static org.mockito.Matchers.any;
    import static org.mockito.Mockito.times;
    import static org.mockito.Mockito.verify;
    import static org.testng.Assert.*;
    

    /**

    • AOP测试
      */
      @RunWith(SpringRunner.class)
      @SpringBootTest(classes = {Application.class})// 指定启动类
      @TestExecutionListeners(listeners = MockitoTestExecutionListener.class)//开启Mockito的支持
      @Slf4j
      public class SpringBootAopTest extends AbstractTestNGSpringContextTests {

      //声明一个被Mockito.spy过的Bean
      @SpyBean
      private HelloAspect helloAspect;

      @Autowired
      private HelloService helloService;

      @Test
      public void testFooService() {
      //判断helloService对象是不是HelloServiceImpl
      assertNotEquals(helloService.getClass(), HelloServiceImpl.class);

       <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//接下来通过AopUtils、AopProxyUtils、AopTestUtils来判断helloService是否是代理的对象</span></span></span></span></span>
       <span class="token function">assertTrue</span><span class="token punctuation">(</span>AopUtils<span class="token punctuation">.</span><span class="token function">isAopProxy</span><span class="token punctuation">(</span>helloService<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token function">assertTrue</span><span class="token punctuation">(</span>AopUtils<span class="token punctuation">.</span><span class="token function">isCglibProxy</span><span class="token punctuation">(</span>helloService<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
       <span class="token function">assertEquals</span><span class="token punctuation">(</span>AopProxyUtils<span class="token punctuation">.</span><span class="token function">ultimateTargetClass</span><span class="token punctuation">(</span>helloService<span class="token punctuation">)</span><span class="token punctuation">,</span> HelloServiceImpl<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
       <span class="token function">assertEquals</span><span class="token punctuation">(</span>AopTestUtils<span class="token punctuation">.</span><span class="token function">getTargetObject</span><span class="token punctuation">(</span>helloService<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> HelloServiceImpl<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token function">assertEquals</span><span class="token punctuation">(</span>AopTestUtils<span class="token punctuation">.</span><span class="token function">getUltimateTargetObject</span><span class="token punctuation">(</span>helloService<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> HelloServiceImpl<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
       <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">/**
        * 但是证明HelloServiceImpl Bean被代理并不意味着HelloAspect生效了(假设此时有多个</span></span></span><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag"><span class="hljs-comment"><span class="hljs-doctag">@Aspect</span></span></span></span></span></span></span><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">),
        * 那么我们还需要验证HelloServiceImpl.getVal的行为。
        * 这里调用两次:
        */</span></span></span></span></span>
       <span class="token function">assertEquals</span><span class="token punctuation">(</span>helloService<span class="token punctuation">.</span><span class="token function">getVal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"aopResult"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token function">assertEquals</span><span class="token punctuation">(</span>helloService<span class="token punctuation">.</span><span class="token function">getVal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string"><span class="hljs-string">"aopResult"</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
       <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//通过MockitoTestExecutionListener来监听是否是调用了两次helloService.getVal()方法</span></span></span></span></span>
       <span class="token comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment"><span class="hljs-comment">//注意这一行代码测试的是helloAspect的行为,而不是helloService的行为</span></span></span></span></span>
       <span class="token function">verify</span><span class="token punctuation">(</span>helloAspect<span class="token punctuation">,</span> <span class="token function">times</span><span class="token punctuation">(</span><span class="token number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number"><span class="hljs-number">2</span></span></span></span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">changeGetVal</span><span class="token punctuation">(</span><span class="token function">any</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      

      }
      }

    测试结果是通过。

    springboot系列学习笔记全部文章请移步值博主专栏**: spring boot 2.X/spring cloud Greenwich
    由于是一系列文章,所以后面的文章可能会使用到前面文章的项目。springboot系列代码全部上传至GitHub:https://github.com/liubenlong/springboot2_demo
    本系列环境:Java11;springboot 2.1.1.RELEASE;springcloud Greenwich.RELEASE;MySQL 8.0.5;

    参考资料

    官方文档
    spring-test-examples
    springboot(16)Spring Boot使用单元测试

                        原文地址:https://blog.csdn.net/liubenlong007/article/details/85398181            </div>
  • 相关阅读:
    Spring MVC Ajax 嵌套表单数据的提交
    Spring MVC 过滤静态资源访问
    Spring MVC 页面跳转时传递参数
    IDEA Maven 三层架构 2、运行 springMVC
    IDEA Maven 三层架构 1、基本的Archetype 搭建
    EasyUI DataGrid 基于 Ajax 自定义取值(loadData)
    Spring MVC Ajax 复杂参数的批量传递
    Mybatis Sql片段的应用
    在 Tomcat 8 部署多端口项目
    自动升级的设计思路与实现
  • 原文地址:https://www.cnblogs.com/jpfss/p/11548261.html
Copyright © 2011-2022 走看看