日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
外部依賴太多,如何寫 Java 單元測(cè)試?

本文轉(zhuǎn)載自微信公眾號(hào)「碼農(nóng)私房話」,作者Liew 。轉(zhuǎn)載本文請(qǐng)聯(lián)系碼農(nóng)私房話公眾號(hào)。

目前創(chuàng)新互聯(lián)公司已為1000多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、河北網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

事出有因

在日常的開發(fā)中,很多人習(xí)慣性地寫完需求代碼后,嗖的一聲用 Postman 模擬真實(shí)請(qǐng)求或?qū)憥讉€(gè) JUnit 的單元測(cè)試跑功能點(diǎn),只要沒(méi)有問(wèn)題就上線了,但其實(shí)這存在很大風(fēng)險(xiǎn),一方面無(wú)法驗(yàn)證業(yè)務(wù)邏輯的不同分支,另外一方面需嚴(yán)重依賴中間件資源才能運(yùn)行測(cè)試用例,占用大量資源。

秣馬厲兵

Mockito是一個(gè)非常優(yōu)秀的模擬框架,可以使用它簡(jiǎn)潔的API來(lái)編寫漂亮的測(cè)試代碼,它的測(cè)試代碼可讀性高同時(shí)會(huì)產(chǎn)生清晰的錯(cuò)誤日志。

添加 maven 依賴

 
 
 
 
  1.  
  2.     org.mockito 
  3.     mockito-core 
  4.     3.3.3 
  5.     test 
  6.  

注意:Mockito 3.X 版本使用了 JDK8 API,但功能與 2.X 版本并沒(méi)有太大的變化。

指定 MockitoJUnitRunner

 
 
 
 
  1. @RunWith(MockitoJUnitRunner.class) 
  2. public class MockitoDemoTest { 
  3.  
  4.     //注入依賴的資源對(duì)象 
  5.     @Mock 
  6.     private MockitoTestService mockitoTestService; 
  7.     @Before 
  8.     public void before(){ 
  9.         MockitoAnnotations.initMocks(this); 
  10.     } 

從代碼中觀察到,使用 @Mock 注解標(biāo)識(shí)哪些對(duì)象需要被 Mock,同時(shí)在執(zhí)行測(cè)試用例前初始化 MockitoAnnotations.initMocks(this) 告訴框架使 Mock 相關(guān)注解生效。

驗(yàn)證對(duì)象行為 Verify

 
 
 
 
  1. @Test 
  2. public void testVerify(){ 
  3.     //創(chuàng)建mock 
  4.     List mockedList = mock(List.class); 
  5.     mockedList.add("1"); 
  6.     mockedList.clear(); 
  7.     //驗(yàn)證list調(diào)用過(guò)add的操作行為 
  8.     verify(mockedList).add("1"); 
  9.     //驗(yàn)證list調(diào)用過(guò)clear的操作行為 
  10.     verify(mockedList).clear(); 
  11.     //使用內(nèi)建anyInt()參數(shù)匹配器,并存根 
  12.     when(mockedList.get(anyInt())).thenReturn("element"); 
  13.     System.out.println(mockedList.get(2)); //此處輸出為element 
  14.     verify(mockedList).get(anyInt()); 

存根 stubbing

stubbing 完全是模擬一個(gè)外部依賴、用來(lái)提供測(cè)試時(shí)所需要的數(shù)據(jù)。

 
 
 
 
  1. @Test 
  2. public void testStub(){ 
  3.     //可以mock具體的類,而不僅僅是接口 
  4.     LinkedList mockedList = mock(LinkedList.class); 
  5.     //存根(stubbing) 
  6.     when(mockedList.get(0)).thenReturn("first"); 
  7.     when(mockedList.get(1)).thenThrow(new RuntimeException()); 
  8.     //下面會(huì)打印 "first" 
  9.     System.out.println(mockedList.get(0)); 
  10.     //下面會(huì)拋出運(yùn)行時(shí)異常 
  11.     System.out.println(mockedList.get(1)); 
  12.     //下面會(huì)打印"null" 因?yàn)間et(999)沒(méi)有存根(stub) 
  13.     System.out.println(mockedList.get(999)); 
  14.     doThrow(new RuntimeException()).when(mockedList).clear(); 
  15.     //下面會(huì)拋出 RuntimeException: 
  16.     mockedList.clear(); 
  • 存根(stub)可以覆蓋,測(cè)試方法可以覆蓋全局設(shè)置的通用存根。
  • 一旦做了存根,無(wú)論這個(gè)方法被調(diào)用多少次,方法將總是返回存根的值。

存根的連續(xù)調(diào)用

 
 
 
 
  1. @Test 
  2. public void testStub() { 
  3.     when(mock.someMethod("some arg")) 
  4.     .thenThrow(new RuntimeException()) 
  5.     .thenReturn("foo"); 
  6.     mock.someMethod("some arg"); //第一次調(diào)用:拋出運(yùn)行時(shí)異常 
  7.     //第二次調(diào)用: 打印 "foo" 
  8.     System.out.println(mock.someMethod("some arg")); 
  9.     //任何連續(xù)調(diào)用: 還是打印 "foo" (最后的存根生效). 
  10.     System.out.println(mock.someMethod("some arg")); 
  11.     //可供選擇的連續(xù)存根的更短版本: 
  12.     when(mock.someMethod("some arg")).thenReturn("one", "two", "three"); 
  13.     when(mock.someMethod(anyString())).thenAnswer(new Answer() { 
  14.         Object answer(InvocationOnMock invocation) { 
  15.             Object[] args = invocation.getArguments(); 
  16.             Object mock = invocation.getMock(); 
  17.             return "called with arguments: " + args; 
  18.         } 
  19.     }); 
  20.     // "called with arguments: foo 
  21.     System.out.println(mock.someMethod("foo")); 

在做方法存根時(shí),可以指定不同時(shí)機(jī)需要提供的測(cè)試數(shù)據(jù),例如第一次調(diào)用返回 xxx,第二次調(diào)用時(shí)拋出異常等。

參數(shù)匹配器

 
 
 
 
  1. @Test 
  2. public void testArugument{ 
  3.     //使用內(nèi)建anyInt()參數(shù)匹配器 
  4.     when(mockedList.get(anyInt())).thenReturn("element"); 
  5.     System.out.println(mockedList.get(999)); //打印 "element" 
  6.     //同樣可以用參數(shù)匹配器做驗(yàn)證 
  7.     verify(mockedList).get(anyInt()); 
  8.  
  9.     //注意:如果使用參數(shù)匹配器,所有的參數(shù)都必須通過(guò)匹配器提供。 
  10.     verify(mock) 
  11.     .someMethod(anyInt(), anyString(), eq("third argument")); 
  12.     //上面是正確的 - eq(0也是參數(shù)匹配器),而下面的是錯(cuò)誤的 
  13.     verify(mock) 
  14.     .someMethod(anyInt(), anyString(), "third argument"); 

驗(yàn)證調(diào)用次數(shù)

 
 
 
 
  1. @Test 
  2. public void testVerify{ 
  3.     List mockedList = new ArrayList(); 
  4.     mockedList.add("once"); 
  5.     mockedList.add("twice"); 
  6.     mockedList.add("twice"); 
  7.     mockedList.add("three times"); 
  8.     mockedList.add("three times"); 
  9.     mockedList.add("three times"); 
  10.     //下面兩個(gè)驗(yàn)證是等同的 - 默認(rèn)使用times(1) 
  11.     verify(mockedList).add("once"); 
  12.     verify(mockedList, times(1)).add("once"); 
  13.     verify(mockedList, times(2)).add("twice"); 
  14.     verify(mockedList, times(3)).add("three times"); 
  15.     //使用using never()來(lái)驗(yàn)證. never()相當(dāng)于 times(0) 
  16.     verify(mockedList, never()).add("never happened"); 
  17.     //使用 atLeast()/atMost()來(lái)驗(yàn)證 
  18.     verify(mockedList, atLeastOnce()).add("three times"); 
  19.     verify(mockedList, atLeast(2)).add("five times"); 
  20.     verify(mockedList, atMost(5)).add("three times"); 

驗(yàn)證調(diào)用順序

 
 
 
 
  1. @Test 
  2. public void testOrder() 
  3.     // A. 單個(gè)Mock,方法必須以特定順序調(diào)用 
  4.     List singleMock = mock(List.class); 
  5.  
  6.     //使用單個(gè)Mock 
  7.     singleMock.add("was added first"); 
  8.     singleMock.add("was added second"); 
  9.  
  10.     //為singleMock創(chuàng)建 inOrder 檢驗(yàn)器 
  11.     InOrder inOrder = inOrder(singleMock); 
  12.  
  13.     //確保add方法第一次調(diào)用是用"was added first",然后是用"was added second" 
  14.     inOrder.verify(singleMock).add("was added first"); 
  15.     inOrder.verify(singleMock).add("was added second"); 

以上是 Mockito 框架常用的使用方式,但 Mockito 有一定的局限性, 它只能 Mock 類或者接口,對(duì)于靜態(tài)、私有及final方法的 Mock 則無(wú)能為力了。

而 PowerMock 正是彌補(bǔ)這塊的缺陷,它的實(shí)現(xiàn)原理如下:

  • 當(dāng)某個(gè)測(cè)試方法被注解 @PrepareForTest 標(biāo)注后,在運(yùn)行測(cè)試用例時(shí)會(huì)創(chuàng)建一個(gè)新的 MockClassLoader 實(shí)例并加載該測(cè)試用例使用到的類(系統(tǒng)類除外)。
  • PowerMock 會(huì)根據(jù)你的 mock 要求,去修改寫在注解 @PrepareForTest 里的 class 文件內(nèi)容(調(diào)用非系統(tǒng)的靜態(tài)、Final方法),若是包含調(diào)用系統(tǒng)的方法則修改調(diào)用系統(tǒng)方法的類的 class 文件內(nèi)容達(dá)到滿足需求 。

但值得高興的是在 Mockito2.7.2 及更高版本添加了對(duì) final 類及方法支持[1] 。

同樣, Mockito3.4.0 及更高版本支持對(duì)靜態(tài)方法的 Mock[2],雖然是處于孵化階段,但對(duì)于我們做單元測(cè)試而言是已經(jīng)足夠了。

決勝之機(jī)

大多數(shù)項(xiàng)目使用了 Spring 或 Spring Boot 作為基礎(chǔ)框架,研發(fā)只需要關(guān)心業(yè)務(wù)邏輯即可。

在代碼例子中將使用 Junit5 的版本,因此要求 Spring boot版本必須是2.2.0版本或以上,采用 Mockito3.5.11 的版本作為 Mock 框架,減少項(xiàng)目對(duì) PowerMock 的依賴,另外還有一個(gè)重要原因是因?yàn)槟壳癙owerMock不支持 Junit5,無(wú)法在引入 PowerMock 后使用Junit5 的相關(guān)功能及API,本文項(xiàng)目代碼地址:https://github.com/GoQeng/spring-mockito3-demo。

maven 配置

 
 
 
 
  1.  
  2.     1.8 
  3.     3.5.11 
  4.     1.10.15 
  5.     3.13.4 
  6.     5.1.48 
  7.     0.8.6 
  8.     5.6.2 
  9.     1.1.1 
  10.     2.1.3 
  11.     3.8.1 
  12.     2.12.4 
  13.     1.4.197 
  14.  
  15.  
  16.  
  17.      
  18.      
  19.         org.springframework.boot 
  20.         spring-boot-starter-web 
  21.      
  22.  
  23.      
  24.         org.springframework.boot 
  25.         spring-boot-starter-test 
  26.         test 
  27.          
  28.              
  29.                 org.mockito 
  30.                 mockito-core 
  31.              
  32.              
  33.                 org.junit.vintage 
  34.                 junit-vintage-engine 
  35.              
  36.          
  37.      
  38.  
  39.      
  40.      
  41.         org.mockito 
  42.         mockito-core 
  43.         ${mockito.version} 
  44.         compile 
  45.          
  46.              
  47.                 net.bytebuddy 
  48.                 byte-buddy 
  49.              
  50.              
  51.                 net.bytebuddy 
  52.                 byte-buddy-agent 
  53.              
  54.          
  55.      
  56.      
  57.      
  58.         net.bytebuddy 
  59.         byte-buddy 
  60.         ${byte-buddy.version} 
  61.      
  62.  
  63.      
  64.         net.bytebuddy 
  65.         byte-buddy-agent 
  66.         ${byte-buddy.version} 
  67.         test 
  68.      
  69.  
  70.      
  71.         org.mockito 
  72.         mockito-inline 
  73.         ${mockito.version} 
  74.         test 
  75.      
  76.  
  77.      
  78.      
  79.         org.mybatis.spring.boot 
  80.         mybatis-spring-boot-starter 
  81.         ${mybatis-spring.version} 
  82.      
  83.  
  84.      
  85.      
  86.         org.redisson 
  87.         redisson-spring-boot-starter 
  88.         ${redisson-spring.version} 
  89.          
  90.              
  91.                 junit 
  92.                 junit 
  93.              
  94.          
  95.         compile 
  96.      
  97.  
  98.      
  99.      
  100.         mysql 
  101.         mysql-connector-java 
  102.         ${mysql.version} 
  103.      
  104.  
  105.      
  106.      
  107.         org.jacoco 
  108.         jacoco-maven-plugin 
  109.         ${jacoco.version} 
  110.      
  111.  
  112.      
  113.      
  114.         org.junit.jupiter 
  115.         junit-jupiter 
  116.         ${junit-jupiter.version} 
  117.         test 
  118.      
  119.  
  120.      
  121.         org.junit.platform 
  122.         junit-platform-runner 
  123.         ${junit-platform.version} 
  124.          
  125.              
  126.                 junit 
  127.                 junit 
  128.              
  129.          
  130.      
  131.  
  132.      
  133.      
  134.         com.h2database 
  135.         h2 
  136.         ${h2.version} 
  137.         test 
  138.          
  139.              
  140.                 junit 
  141.                 junit 
  142.              
  143.          
  144.      
  145.  
  146.  
  147.  
  148.      
  149.          
  150.             org.apache.maven.plugins 
  151.             maven-surefire-plugin 
  152.             ${maven-surefire.version} 
  153.              
  154.                  
  155.                  
  156.                     test 
  157.                      
  158.                         test 
  159.                      
  160.                  
  161.              
  162.              
  163.                 once 
  164.                 false 
  165.                  
  166.                     **/SuiteTest.java 
  167.                  
  168.              
  169.          
  170.          
  171.             org.apache.maven.plugins 
  172.             maven-compiler-plugin 
  173.             ${maven-compiler.version} 
  174.              
  175.                 
  176.                 8 
  177.              
  178.          
  179.          
  180.             org.jacoco 
  181.             jacoco-maven-plugin 
  182.             ${jacoco.version} 
  183.              
  184.                  
  185.                      
  186.                         prepare-agent 
  187.                      
  188.                  
  189.                  
  190.                  
  191.                     report 
  192.                     test 
  193.                      
  194.                         report 
  195.                      
  196.                  
  197.              
  198.          
  199.      
  200.  
  201.  
  202.      
  203.          
  204.             org.jacoco 
  205.             jacoco-maven-plugin 
  206.              
  207.                  
  208.                      
  209.                          
  210.                         report 
  211.                      
  212.                  
  213.              
  214.          
  215.      
  216.  

maven 運(yùn)行測(cè)試用例是通過(guò)調(diào)用 maven 的 surefire 插件并 fork 一個(gè)子進(jìn)程來(lái)執(zhí)行用例的。

forkMode 屬性指明是為每個(gè)測(cè)試創(chuàng)建一個(gè)進(jìn)程還是所有測(cè)試共享同一個(gè)進(jìn)程完成,forkMode 設(shè)置值有 never、once、always 、pertest 。

  • pretest:每一個(gè)測(cè)試創(chuàng)建一個(gè)新進(jìn)程,為每個(gè)測(cè)試創(chuàng)建新的JVM進(jìn)程是單獨(dú)測(cè)試的最徹底方式,但也是最慢的,不適合持續(xù)回歸。
  • once:在一個(gè)進(jìn)程中進(jìn)行所有測(cè)試。once 為默認(rèn)設(shè)置,在持續(xù)回歸時(shí)建議使用默認(rèn)設(shè)置。
  • always:在一個(gè)進(jìn)程中并行的運(yùn)行腳本,Junit4.7 以上版本才可以使用,surefire 的版本要在 2.6 以上提供這個(gè)功能,其中 threadCount 執(zhí)行時(shí),指定可分配的線程數(shù)量,只和參數(shù) parallel 配合使用有效,默認(rèn)為 5。
  • never:從不創(chuàng)建新進(jìn)程進(jìn)行測(cè)試。

環(huán)境準(zhǔn)備

在項(xiàng)目中 test 目錄下建立測(cè)試入口類 TestApplication.java,將外部依賴 Redis 單獨(dú)配置到 DependencyConfig.java 中,同時(shí)需要在 TestApplication.class 中排除對(duì) Redis 或 Mongodb 的自動(dòng)注入配置等。

注意:將外部依賴配置到DependencyConfig并不是必要的,此步驟的目的是為了避免每個(gè)單元測(cè)試類運(yùn)行時(shí)都會(huì)重啟 Spring 上下文,可采用 @MockBean 的方式在代碼中引入外部依賴資源替代此方法。

 
 
 
 
  1. @Configuration 
  2. public class DependencyConfig { 
  3.  
  4.     @Bean 
  5.     public RedissonClient getRedisClient() { 
  6.         return Mockito.mock(RedissonClient.class); 
  7.     } 
  8.  
  9.     @Bean 
  10.     public RestTemplate restTemplate() { 
  11.         return Mockito.mock(RestTemplate.class); 
  12.     } 

接著在測(cè)試入口類中通過(guò) @ComponentScan 對(duì)主入口啟動(dòng)類 Application.class 及 RestClientConfig.class 進(jìn)行排除。

 
 
 
 
  1. @SpringBootApplication 
  2. @ComponentScan(excludeFilters = @ComponentScan.Filter( 
  3.         type = FilterType.ASSIGNABLE_TYPE, 
  4.         classes = {Application.class, RestClientConfig.class})) 
  5. @MapperScan("com.example.mockito.demo.mapper") 
  6. public class TestApplication { 
  7.  

為了不單獨(dú)寫重復(fù)的代碼,我們一般會(huì)把單獨(dú)的代碼抽取出來(lái)作為一個(gè)公共基類,其中 @ExtendWith(SpringExtension.class) 注解目的是告訴 Spring boot 將使用 Junit5 作為運(yùn)行平臺(tái),如果想買中使用 Junit4 的話,則需要使用 @RunWith(SpringRunner.class) 注解告知用 SpringRunner 運(yùn)行啟動(dòng)。

 
 
 
 
  1. @SpringBootTest(classes = TestApplication.class)@ExtendWith(SpringExtension.class) 
  2. public abstract class SpringBaseTest {} 

準(zhǔn)備好配置環(huán)境后,我們便可以開始對(duì)項(xiàng)目的 Mapper、Service、Web 層進(jìn)行測(cè)試了。

Mapper層測(cè)試

對(duì) Mapper 層的測(cè)試主要是驗(yàn)證 SQL 語(yǔ)句及 Mybatis 傳參等準(zhǔn)確性。

 
 
 
 
  1. server: 
  2.   port: 8080 
  3. spring: 
  4.   test: 
  5.     context: 
  6.       cache: 
  7.         max-size: 42 
  8.   main: 
  9.     allow-bean-definition-overriding: true 
  10.   datasource: 
  11.     url: jdbc:h2:mem:test;MODE=MYSQL;DB_CLOSE_DELAY=-1;INIT=runscript from 'classpath:init.sql' 
  12.     username: sa 
  13.     password: 
  14.     driverClassName: org.h2.Driver 
  15.     hikari: 
  16.       minimum-idle: 5 
  17.       maximum-pool-size: 15 
  18.       auto-commit: true 
  19.       idle-timeout: 30000 
  20.       pool-name: DatebookHikariCP 
  21.       max-lifetime: 1800000 
  22.       connection-timeout: 10000 
  23.       connection-test-query: SELECT 1 
  24.  
  25. mybatis: 
  26.   type-aliases-package: com.example.mockito.demo.domain 
  27.   mapper-locations: 
  28.     - classpath:mapper/*.xml 

對(duì) Mapper 層的測(cè)試并沒(méi)有采取 Mock 的方式,而是采用 H2 內(nèi)存數(shù)據(jù)庫(kù)的方式模擬真實(shí)數(shù)據(jù)庫(kù),同時(shí)也避免由于測(cè)試數(shù)據(jù)給真實(shí)數(shù)據(jù)庫(kù)帶來(lái)的影響。

 
 
 
 
  1. jdbc:h2:mem:test;MODE=MYSQL;DB_CLOSE_DELAY=-1;INIT=runscript from 'classpath:init.sql' 

配置 H2 數(shù)據(jù)庫(kù)信息,同時(shí) INIT 指定在創(chuàng)建連接時(shí)會(huì)執(zhí)行類路徑下的 init.sql 即建表 SQL 。

 
 
 
 
  1. public class DemoMapperTest extends SpringBaseTest { 
  2.  
  3.     @Resource 
  4.     private DemoMapper demoMapper; 
  5.  
  6.     @Test 
  7.     public void testInsert() { 
  8.         Demo demo = new Demo(); 
  9.         demo.setName("test"); 
  10.         demoMapper.insert(demo); 
  11.  
  12.         Integer id = demo.getId(); 
  13.         Demo model = demoMapper.getDetail(id); 
  14.         Assert.assertNotNull(model); 
  15.         Assert.assertEquals(demo.getName(), model.getName()); 
  16.     } 
  17.  
  18.     @Test 
  19.     public void testGetList() { 
  20.         Demo demo = new Demo(); 
  21.         demo.setName("test"); 
  22.         demoMapper.insert(demo); 
  23.  
  24.         List demoList = demoMapper.getList(); 
  25.         Assert.assertNotNull(demoList); 
  26.         Assert.assertEquals(1, demoList.size()); 
  27.     } 

Service層測(cè)試

一般項(xiàng)目的業(yè)務(wù)邏輯寫在 service 層,需要寫更多的測(cè)試用例驗(yàn)證業(yè)務(wù)代碼邏輯性及準(zhǔn)確性,盡可能的覆蓋到業(yè)務(wù)代碼的分支邏輯。

 
 
 
 
  1. public class DemoServiceTest extends SpringBaseTest { 
  2.  
  3.   @Resource 
  4.   private DemoService demoService; 
  5.   @Resource 
  6.   private RedissonClient redissonClient; 
  7.  
  8.   @Resource 
  9.   private RestTemplate restTemplate; 
  10.  
  11.   @BeforeEach 
  12.   public void setUp() { 
  13.       MockitoAnnotations.openMocks(this); 
  14.   } 
  15.  
  16.   @Test 
  17.   public void testGetList() { 
  18.       //測(cè)試第一個(gè)分支邏輯 
  19.       RAtomicLong rAtomicLong = Mockito.mock(RAtomicLong.class); 
  20.       Mockito.when(redissonClient.getAtomicLong(ArgumentMatchers.anyString())).thenReturn(rAtomicLong); 
  21.       long count = 4L; 
  22.       Mockito.when(rAtomicLong.incrementAndGet()).thenReturn(count); 
  23.       List demoList = demoService.getList(); 
  24.       Assert.assertTrue(demoList != null && demoList.size() == 1); 
  25.       Demo demo = demoList.get(0); 
  26.       Assert.assertNotNull(demo); 
  27.       Assert.assertEquals(Integer.valueOf(4), demo.getId()); 
  28.       Assert.assertEquals("testCount4", demo.getName()); 
  29.  
  30.       //測(cè)試第二個(gè)分支邏輯 
  31.       Mockito.when(redissonClient.getAtomicLong(ArgumentMatchers.anyString())).thenReturn(rAtomicLong); 
  32.       count = 1L; 
  33.       Mockito.when(rAtomicLong.incrementAndGet()).thenReturn(count); 
  34.  
  35.       MockedStatic aesUtilMockedStatic = Mockito.mockStatic(AESUtil.class); 
  36.       aesUtilMockedStatic.when(() -> AESUtil.encrypt(ArgumentMatchers.eq("test"), ArgumentMatchers.eq("1234567890123456"))) 
  37.               .thenReturn("demo"); 
  38.  
  39.       demoList = demoService.getList(); 
  40.       Assert.assertTrue(demoList != null && demoList.size() == 1); 
  41.       Demo encryptDemo = demoList.get(0); 
  42.       Assert.assertNotNull(encryptDemo); 
  43.       Assert.assertEquals(Integer.valueOf(1), encryptDemo.getId()); 
  44.       Assert.assertEquals("testEncrypt", encryptDemo.getName()); 
  45.  
  46.       //測(cè)試第三個(gè)分支邏輯 
  47.       Mockito.when(redissonClient.getAtomicLong(ArgumentMatchers.anyString())).thenReturn(rAtomicLong); 
  48.       count = 1L; 
  49.       Mockito.when(rAtomicLong.incrementAndGet()).thenReturn(count); 
  50.  
  51.       //執(zhí)行真實(shí)方法 
  52.       aesUtilMockedStatic.when(() -> AESUtil.encrypt(ArgumentMatchers.eq("test"), ArgumentMatchers.eq("1234567890123456"))) 
  53.               .thenCallRealMethod(); 
  54.  
  55.       String mobileUrl = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel="; 
  56.       MobileInfoDTO mobileInfoDTO = new MobileInfoDTO(); 
  57.       mobileInfoDTO.setName("testMobile"); 
  58.       mobileInfoDTO.setLocation("testLocation"); 
  59.       Mockito.when(restTemplate.getForObject(mobileUrl, MobileInfoDTO.class)).thenReturn(mobileInfoDTO); 
  60.       demoList = demoService.getList(); 
  61.       Assert.assertNotNull(demoList); 
  62.       Assert.assertEquals(1, demoList.size()); 
  63.       Demo demo1 = demoList.get(0); 
  64.       Assert.assertNotNull(demo1); 
  65.       Assert.assertEquals(mobileInfoDTO.getName(), demo1.getName()); 
  66.     } 

WEB層測(cè)試

 
 
 
 
  1. public class DemoControllerTest extends SpringBaseTest { 
  2.  
  3.   private MockMvc mockMvc; 
  4.  
  5.   @Mock 
  6.   p
    當(dāng)前題目:外部依賴太多,如何寫 Java 單元測(cè)試?
    本文地址:http://www.5511xx.com/article/ccsgdco.html