一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Spring測試 其實很簡單

Spring測試 其實很簡單

2020-05-26 12:10Sandbox Wang JAVA教程

這篇文章主要為大家詳細介紹了Spring測試,其實很簡單,揭開集成測試神秘的面紗,感興趣的小伙伴們可以參考一下

在過去的職業生涯里,我經常發現有些人不寫測試代碼,而他們聲稱不寫的理由是無法輕易地寫出覆蓋多個不同模塊的測試用例。好吧,我相信他們中的大部分要么是缺乏一些比較易掌握的技術手段,要么就是沒時間來把它搞清楚,畢竟工作中總會有進度之類的各種壓力。因為不知道該如何測試,所以就經常忽略集成測試,由此帶來的問題就是越來越糟糕的軟件、越來越多的BUG和更加失望的客戶。所以我想分享一些個人的經驗,揭開集成測試神秘的面紗。 

如何對基于Spring的工程更好地進行集成測試
使用工具: Spring, JUnit, Mockito
想象有這樣一個Spring工程,它集成了一些外部服務,例如,一些銀行的web服務。那么,為這個工程寫測試用例以及在持續集成系統中完成這些測試時所遇到的問題基本都差不多:
 1.每次測試都會有交易進行,每次交易都需要付出金錢成本,這些成本最終由客戶承擔;
 2.測試時發出的過多的請求有可能被認為是惡意請求,可能造成在銀行的賬戶被封,后果是測試失敗;
 3.當使用非生產環境進行測試時,測試結果并不十分可靠,同樣,后果是測試失敗。
通常情況下,你對單個類進行測試的時候,問題很容易解決,因為你可以虛擬一些外部服務來供調用。但是當對整個巨大的業務流程進行測試的時候,意味你需要對多個部件進行測試,這時,需要你將這些部件都納入到Spring容器中進行管理。所幸,Spring包含了非常優秀的測試框架,允許你將來自生產環境配置文件中的bean注入到測試環境中,但是對那些被調用的外部服務,需要我們自己去寫模擬實現。一般人第一反應可能是在測試的setUp階段對由Spring注入的bean進行重新注入(修改),但是這種方法需要再仔細考慮一下。 

警告:通過這種方式,你的測試代碼打破了容器自身的行為,所以沒法保證在真實的環境中也如你測試的結果一樣。
事實上,我們無需先實現模擬類然后再把它重新注入到所需的bean中,我們可以讓Spring幫助我們一開始就注入模擬類。讓我們用代碼演示一下。
示例工程包含一個名為BankService的類,代表調用的外部服務,一個名為UserBalanceService的類,它會調用BankService。UserBalanceService實現的非常簡單,僅僅完成將余額從String向Double類型的轉換。
BankService.java的源碼:

?
1
2
3
public interface BankService {
 String getBalanceByEmail(String email);
}

BankServiceImpl.java的源碼:

?
1
2
3
4
5
6
public class BankServiceImpl implements BankService {
 @Override
 public String getBalanceByEmail(String email) {
  throw new UnsupportedOperationException("Operation failed due to external exception");
 }
}

UserBalanceService.java的源碼:

?
1
2
3
interface UserBalanceService {
 Double getAccountBalance(String email);
}

UserBalanceServiceImpl.java的源碼:

?
1
2
3
4
5
6
7
8
public class UserBalanceServiceImpl implements UserBalanceService {
 @Autowired
 private BankService bankService;
 @Override
 public Double getAccountBalance(String email) {
  return Double.valueOf(bankService.getBalanceByEmail(email));
 }
}

然后是Spring的XML配置文件,添加所需要的bean聲明。
applicationContext.xml的源代碼:

?
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
 <bean id="bankService" class="ua.eshepelyuk.blog.springtest.springockito.BankServiceImpl"/>
 <bean id="userBalanceService" class="ua.eshepelyuk.blog.springtest.springockito.UserBalanceServiceImpl"/>
</beans>

下面是測試類UserBalanceServiceImplTest.java的源代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/springtest/springockito/applicationContext.xml")
public class UserBalanceServiceImplProfileTest {
 @Autowired
 private UserBalanceService userBalanceService;
 @Autowired
 private BankService bankService;
 @Test
 public void shouldReturnMockedBalance() {
  Double balance = userBalanceService.getAccountBalance("[email protected]");
  assertEquals(balance, Double.valueOf(123.45D));
 }
}

如我們預料的一樣,測試方法報UnsupportedOperationException異常。我們現在的目的是把BankService換成我們的模擬實現。直接使用Mockito來生成factory bean的方法是沒問題的,但是有更好的選擇,使用Springockito框架。繼續之前可以先大概了解一下。 

剩下的問題就簡單了:如何讓Spring注入模擬的bean而不是真實的bean,在Spring 3.1版之前除了新建一個XML配置文件之外沒有其他的方法。但是自從Spring引入了bean的profile定義之后,我們有了更加優雅的解決方式,雖然這種方式也需要一個額外的專門用作測試的XML配置文件。下面是這個用來測試的配置文件testApplicationContext.xml的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
 <import resource="classpath:/springtest/springockito/applicationContext.xml"/>
 <beans profile="springTest">
  <mockito:mock id="bankService" class="ua.eshepelyuk.blog.springtest.springockito.BankService"/>
 </beans>
</beans>

做相應修改過之后的測試類UserBalanceServiceImplProfileTest.java的源代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/springtest/springockito/testApplicationContext.xml")
@ActiveProfiles(profiles = {"springTest"})
public class UserBalanceServiceImplProfileTest {
 @Autowired
 private UserBalanceService userBalanceService;
 @Autowired
 private BankService bankService;
 @Before
 public void setUp() throws Exception {
  Mockito.when(bankService.getBalanceByEmail("[email protected]")).thenReturn(String.valueOf(123.45D));
 }
 @Test
 public void shouldReturnMockedBalance() {
  Double balance = userBalanceService.getAccountBalance("[email protected]");
  assertEquals(balance, Double.valueOf(123.45D));
 }
}

你可能注意到了,在setUp方法里,我們定義了模擬的行為,并且在類上面加了@Profile的注解。這個注解激活了名為springTest的profile,因此使用Springockito模擬的bean就可以自動注入到任何它所需要的地方了。這個測試的運行結果會成功,因為Spring注入了Springockito 所模擬的版本,而不是applicationContext.xml里所聲明的版本。

繼續優化我們的測試
 如果我們能將解決這個問題的方法更加推進一步的話,這篇文章看起來才沒有缺憾。Springockito提供了另外一個名字叫作
 Springockito Annotation的框架,它允許我們在測試類中使用注解來注入模擬類。繼續看下去之前,您最好先去網站上大概瞧瞧。好了,下面是經過修改后的測試代碼。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
UserBalanceServiceImplAnnotationTest.java的源代碼:
 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = SpringockitoContextLoader.class,
 locations = "classpath:/springtest/springockito/applicationContext.xml")
public class UserBalanceServiceImplAnnotationTest {
 @Autowired
 private UserBalanceService userBalanceService;
 @Autowired
 @ReplaceWithMock
 private BankService bankService;
 @Before
 public void setUp() throws Exception {
  Mockito.when(bankService.getBalanceByEmail("[email protected]")).thenReturn(String.valueOf(valueOf(123.45D)));
 }
 @Test
 public void shouldReturnMockedBalance() {
  Double balance = userBalanceService.getAccountBalance("[email protected]");
  assertEquals(balance, valueOf(123.45D));
 }
}

請注意,這里并沒有新引入的XML配置文件,而是直接使用了正式環境的applicationContext.xml。我們使用@ReplaceWithMock這個注解標記了類型為BankService的bean,而后在setUp方法中對模擬類的行為進行了定義。

后記
Springockito-annotations項目有個巨大的優點,那就是,它使我們的測試代碼建立在依賴覆蓋的基礎之上,通過這樣,我們既不需要定義額外的XML配置文件,也不需要為了測試而去改動生產環境的配置文件。如果不使用Springockito-annotations的話,我們除了定義額外的XML配置文件別無他選了。因此,我強烈建議您在集成測試中使用Springockito-annotations,這樣你可以最大限度減少測試用例對生產代碼的影響,也能消除維護額外XML配置文件的負擔。
附言
為Spring工程寫集成測試真是簡單多了吧,文章中的代碼參考自我的GitHub。 

譯文鏈接:http://www.codeceo.com/article/spring-test-is-easy.html
英文原文:Test Me If You Can #1 (Spring Framework)
翻譯作者:碼農網 – Sandbox Wang

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 草逼视频网站 | 国内自拍视频在线观看 | 日本高清视频在线观看 | 亚洲无线一二三四区 | 韩国黄色网址 | 亚瑟天堂久久一区二区影院 | 色一情| 污污在线免费观看 | 欧美伦乱 | 2020年最新国产精品视频免费 | 高清欧美videossexo免费 | 动漫美女胸被狂揉扒开吃奶动态图 | 99热com| 国语自产拍在线播放不卡 | 欧美日韩一区二区中文字幕视频 | 天天做天天爽天天谢 | 国内精品福利丝袜视频_速 国内精品91久久久久 | 香蕉国产人午夜视频在线 | 国内精品91最新在线观看 | 2023最新伦理片 | 大香人蕉免费视频75 | 门卫老张和女警花小说 | 3d美女触手怪爆羞羞漫画 | 四虎影院免费视频 | 国产在线欧美日韩精品一区二区 | 四大美女思春艳史片 | 国产亚洲综合精品一区二区三区 | 国产第9页| 精品国产线拍大陆久久尤物 | 亚洲天堂网站 | 免费大片a一级一级 | 亚洲国产精品久久久久久 | 亚洲国产精品线在线观看 | 麻豆天美精东果冻传媒在线 | 2020年国产精品午夜福利在线观看 | 午夜视频一区二区三区 | 男女姓交大视频免费观看 | kk4kk免费毛片 | 久热这里只有精品99国产6 | 互换身体全集免费观看 | 欧美亚洲国产精品久久久 |