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"><</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">></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"><</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">/></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"><</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">/></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"></</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">></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-wy\springboot2demo)
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-web
為spring-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"><</span>Stu<span class="token punctuation">></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"><</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">></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"><</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">></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"><</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">></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"><</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">></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"><</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">></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">"\n"</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">></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>