Spring中使用mockito

Mockito介紹與入門(mén)

  1. mockito官網(wǎng)
  2. 5分鐘mockito入門(mén)
  3. Mockito: 一個(gè)強(qiáng)大的用于Java開(kāi)發(fā)的模擬測(cè)試框架

Spring中正常使用Mockito

demo代碼:

 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @ContextConfiguration(locations = { "classpath:testApplicationContext.xml" })
 3 public class SpringMockitoTest {
 4  
 5     @Mock
 6     private ApiService mockApiService;
 7  
 8     @Before
 9     public void initMocks() {
10         MockitoAnnotations.initMocks(this);
11         when(mockApiService.test()).thenReturn("ok");
12     }
13  
14     @Test
15     public void should_success_when_testApiService() {
16         String result = mockApiService.test();
17         Assert.assertEquals("ok", result);
18     }
19 }
20  
21 @Component
22 public class ApiService {
23  
24     @Autowired
25     private TestApiService testApiService;
26  
27     public String test() {
28         String connect = testApiService.connect();
29         connect += "test";//test自己的業(yè)務(wù)
30         return connect;
31     }
32 }
33  
34 @Component
35 public class TestApiService {
36     public String connect() {
37         return "error";
38     }
39  
40     public String  findFromDb() {
41         return "db_data";
42     }
43 }

正常使用spring和mockito中缸匪,我們把需要的mock的ApiService給mock掉除秀,但是我們更想的是把TestApiService中的connect方法mock掉,這樣就可以測(cè)試我們自己的代碼,也就是ApiService中test方法自己的業(yè)務(wù)圆兵。

Spring中mock任何容器內(nèi)對(duì)象

上面的demo, 我們?nèi)绾蝝ock掉TestApiService中的test方法?


因?yàn)門(mén)estApiService是Spring容器管理的bean, 并且ApiService中使用到TestApiService, 所以我們把ApiService中引用的TestApiService替換成我們的mock對(duì)象即可。

Spring框架有個(gè)反射工具ReflectionTestUtils可以把一個(gè)對(duì)象中屬性設(shè)置為新值仅颇,我們可以使用:

ReflectionTestUtils.setField(apiService, "testApiService", spyTestAPiService);

把我們mock的testApiService放到apiService中剖膳,這樣apiService調(diào)用就是我們mock的對(duì)象了;但是默認(rèn)spring中apiService對(duì)象是代理對(duì)象格侯,不能直接把值設(shè)置到屬性上鼻听,所以我們自己需寫(xiě)個(gè)小工具類(lèi),最后如下:

ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", spyTestApiService);

完整demo如下:

 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @ContextConfiguration(locations = { "classpath:testApplicationContext.xml" })
 3 public class SpringMockitoTest {
 4  
 5     @Autowired
 6     private ApiService apiService;
 7     @Mock
 8     private TestApiService spyTestApiService;
 9     @Autowired
10     private TestApiService testApiService;
11  
12     @Before
13     public void initMocks() throws Exception {
14         MockitoAnnotations.initMocks(this);
15         ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", spyTestApiService);
16         when(spyTestApiService.connect()).thenReturn("ok");
17     }
18  
19     @After
20     public void clearMocks() throws Exception {
21         ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", testApiService);
22     }
23  
24     @Test
25     public void should_success_when_testApiService() {
26         String result = apiService.test();
27         Assert.assertEquals("oktest", result);
28     }
29 }
30  
31 @Component
32 public class ApiService {
33  
34     @Autowired
35     private TestApiService testApiService;
36  
37     public String test() {
38         String connect = testApiService.connect();
39         connect += "test";//test自己的業(yè)務(wù)
40         return connect;
41     }
42 }
43  
44 @Component
45 public class TestApiService {
46     public String connect() {
47         return "error";
48     }
49  
50     public String  findFromDb() {
51         return "db_data";
52     }
53 }
54  
55 public class AopTargetUtils {
56     /** 
57      * 獲取 目標(biāo)對(duì)象 
58      * @param proxy 代理對(duì)象 
59      * @return  
60      * @throws Exception 
61      */
62     public static Object getTarget(Object proxy) throws Exception {  
63         if(!AopUtils.isAopProxy(proxy)) {  
64             return proxy;//不是代理對(duì)象  
65         }  
66         if(AopUtils.isJdkDynamicProxy(proxy)) {  
67             return getJdkDynamicProxyTargetObject(proxy);  
68         } else { //cglib  
69             return getCglibProxyTargetObject(proxy);  
70         }  
71     }  
72  
73     private static Object getCglibProxyTargetObject(Object proxy) throws Exception {  
74         Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");  
75         h.setAccessible(true);  
76         Object dynamicAdvisedInterceptor = h.get(proxy);  
77         Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");  
78         advised.setAccessible(true);  
79         Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();  
80         return target;  
81     }  
82  
83  
84     private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {  
85         Field h = proxy.getClass().getSuperclass().getDeclaredField("h");  
86         h.setAccessible(true);  
87         AopProxy aopProxy = (AopProxy) h.get(proxy);  
88         Field advised = aopProxy.getClass().getDeclaredField("advised");  
89         advised.setAccessible(true);  
90         Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();  
91         return target;  
92     }  
93 }

最后就是注意測(cè)試之后要還原現(xiàn)場(chǎng),把spring對(duì)象還原联四,尤其在跑maven test的時(shí)候撑碴,否則可能會(huì)影響其他人的測(cè)試。

[本文轉(zhuǎn)載自此處][1]
[1]:http://blog.csdn.net/chuntian_feng/article/details/51871808

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末朝墩,一起剝皮案震驚了整個(gè)濱河市醉拓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌收苏,老刑警劉巖亿卤,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鹿霸,居然都是意外死亡排吴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)懦鼠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钻哩,“玉大人,你說(shuō)我怎么就攤上這事葛闷”锘保” “怎么了双藕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵淑趾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我忧陪,道長(zhǎng)扣泊,這世上最難降的妖魔是什么近范? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮延蟹,結(jié)果婚禮上评矩,老公的妹妹穿的比我還像新娘。我一直安慰自己阱飘,他們只是感情好斥杜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著沥匈,像睡著了一般蔗喂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上高帖,一...
    開(kāi)封第一講書(shū)人閱讀 49,792評(píng)論 1 290
  • 那天缰儿,我揣著相機(jī)與錄音,去河邊找鬼散址。 笑死乖阵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的预麸。 我是一名探鬼主播瞪浸,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吏祸!你這毒婦竟也來(lái)了默终?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤犁罩,失蹤者是張志新(化名)和其女友劉穎齐蔽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體床估,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡含滴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丐巫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谈况。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖递胧,靈堂內(nèi)的尸體忽然破棺而出碑韵,到底是詐尸還是另有隱情,我是刑警寧澤缎脾,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布祝闻,位于F島的核電站,受9級(jí)特大地震影響遗菠,放射性物質(zhì)發(fā)生泄漏联喘。R本人自食惡果不足惜华蜒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望豁遭。 院中可真熱鬧叭喜,春花似錦、人聲如沸蓖谢。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闪幽。三九已至启绰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沟使,已是汗流浹背委可。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腊嗡,地道東北人着倾。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像燕少,于是被迫代替她去往敵國(guó)和親卡者。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理客们,服務(wù)發(fā)現(xiàn)崇决,斷路器,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評(píng)論 6 342
  • 官方wiki5分鐘了解MockitoMockito:一個(gè)強(qiáng)大的用于 Java 開(kāi)發(fā)的模擬測(cè)試框架spring中使用...
    拾壹北閱讀 300評(píng)論 0 1
  • 單元測(cè)試 單測(cè)定義 單元測(cè)試(Unit Testing)又稱(chēng)為模塊測(cè)試, 是針對(duì)程序模塊(軟件設(shè)計(jì)的最小單位)來(lái)進(jìn)...
    運(yùn)維開(kāi)發(fā)筆記閱讀 1,990評(píng)論 0 2
  • “三伏(Dog Day)”是初伏底挫、中伏和末伏的統(tǒng)稱(chēng)恒傻,是一年中最熱的時(shí)節(jié)。每年出現(xiàn)在陽(yáng)歷7月中旬到8月中旬建邓。其氣候特...
    天潤(rùn)老中醫(yī)閱讀 530評(píng)論 1 1