如何使用Mock/Stub模擬對象來對FeignClient進(jìn)行單元測試(UnitTest)

2018.01.15更新

后來在我司架構(gòu)師的指點(diǎn)下,我改用了一種更優(yōu)雅友好的方式來對FeignClient對象進(jìn)行Mock既荚。
首先我們需要一個(gè)jar包

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

spring的這個(gè)jar包下自帶Mock相關(guān)內(nèi)容贴唇。只需要在Test類中使用@MockBean聲明我們所要Mock的FeignClient對象即可搀绣。
如:

@MockBean
private IPromotionController feignPromotionMock

PS:當(dāng)你需要進(jìn)一步使用這個(gè)對象時(shí),你需要自己寫相應(yīng)的斷言戳气。
以上链患。

--------------------------------------2018.01.15更新分割線------------------------------------------------

前言

在搜索引擎使用關(guān)鍵詞mock+feignclient搜索,搜索結(jié)果中最相關(guān)的就是StackOverFlow上的《How to mock feign.Client.Default with Mockito》了瓶您。
本文將會(huì)基于此問答中麻捻,用戶yuz的回答展開纲仍。

該回答提供了一種手動(dòng)模擬對象的實(shí)現(xiàn)方式。至于這種方式屬于mock還是stub贸毕,就見仁見智了郑叠。

本文由作者三汪首發(fā)于簡書。

擴(kuò)展閱讀:

正文

yuz的回答內(nèi)容如下:

As mentioned before, Mockito is not powerful enough. I solved this with a manual mock.
It's easier than it sounds:

MyService.Java

public class MyService{
    //My service stuff      

    private MyFeignClient myFeignClient;

    @Inject //this will work only with constructor injection
    public MyService(MyFeignClient myFeignClient){
        this.MyFeignClient = myFeignClient
    }


    public void myMethod(){
        myFeignClient.remoteMethod(); // We want to mock this method
    }
}

MyFeignClient.Java

@FeignClient("target-service")
public interface MyFeignClient{

    @RequestMapping(value = "/test" method = RequestMethod.GET)
    public void remotemethod();
}

If you want to test the code above while mocking the feignclient, do this:

MyFeignClientMock.java

@Component
public class MyFeignClientMock implements MyFeignClient {

    public void remoteMethod(){
         System.out.println("Mocked remoteMethod() succesfuly");
    }
}

MyServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {

    private MyService myService;

    @Inject
    private MyFeignClientMock myFeignClientMock;

    @Before
    public void setUp(){
       this.myService = new MyService(myFeignClientMock); //inject the mock
    }

    //Do tests normally here...
}

補(bǔ)充和說明

上面的答案可以很好地實(shí)現(xiàn)對FeignClient的mock明棍,但我們需要作進(jìn)一步的補(bǔ)充乡革,如下。具體的修改原因隨后附上击蹲。

MyService.Java

@Service
public class MyService{
    //My service stuff      
    @Autowired
    private MyFeignClient myFeignClient;
    @Autowired
    private MyRepository myRepository;

    @Autowired
    public MyService(MyFeignClient myFeignClient,MyRepository myRepository){
        this.myFeignClient = myFeignClient;
        this.myRepository = myRepository;
    }


    public void myMethod(){
        myFeignClient.remoteMethod(); // We want to mock this method
        myRepository.findAll();
    }
}

MyFeignClient.Java

@FeignClient("target-service")
public interface MyFeignClient{

    @RequestMapping(value = "/test" method = RequestMethod.GET)
    public void remotemethod();
}

MyFeignClientMock.java

@Component
public class MyFeignClientMock implements MyFeignClient {

    public void remoteMethod(){
         System.out.println("Mocked remoteMethod() succesfuly");
    }
}

MyServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {

    private MyService myService;

    @Autowired
    private MyFeignClientMock myFeignClientMock;
    @Autowired
    private MyRepository myRepository;

    @Before
    public void setUp(){
       this.myService = new MyService(myFeignClientMock,myRepository); //inject the mock
    }

    @Test
    public void Test(){
        myService.myMethod();
    }

    //Do  other tests normally here...
}

說明:

  • @Inject是jsr330中的東西署拟。由于Spring支持這個(gè)規(guī)范,也可以使用@Inject來實(shí)現(xiàn)注入。但是通常在Spring中習(xí)慣使用@Autowired來實(shí)現(xiàn)注入歌豺,能用一個(gè)東西解決就用一個(gè)東西解決,我們沒有必要讓代碼更復(fù)雜心包。因此建議使用@Autowired來替代原文中的@Inject类咧。
    擴(kuò)展閱讀:《@Inject和@Autowired以及@Resource區(qū)別》

  • MyService.java中原文可能漏掉了@Service注解,在此做了補(bǔ)充蟹腾。

  • 【重要】:通過構(gòu)造函數(shù)new出來的service對象痕惋,沒有在構(gòu)造函數(shù)中初始化的其他注入會(huì)為空。
    在此我特地在MyService.java中注入了MyRepository并修改了相應(yīng)構(gòu)造函數(shù)進(jìn)行示例娃殖。
    如果構(gòu)造函數(shù)中像原文一樣只傳入MyFeignClient的實(shí)現(xiàn)值戳,那么由于MyRepository沒有被初始化,在調(diào)用myMethod()時(shí)會(huì)出現(xiàn)NullPointerException炉爆。
    同時(shí)堕虹,這也提現(xiàn)了這種實(shí)現(xiàn)方式的一個(gè)弊端:對注入對象多的Service不友好。望周知芬首。


以上赴捞。
希望我的文章對你能有所幫助。
我不能保證文中所有說法的百分百正確郁稍,但我能保證它們都是我的理解和感悟以及拒絕復(fù)制黏貼赦政。
有什么意見、見解或疑惑耀怜,歡迎留言討論恢着。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市财破,隨后出現(xiàn)的幾起案子掰派,更是在濱河造成了極大的恐慌,老刑警劉巖狈究,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碗淌,死亡現(xiàn)場離奇詭異盏求,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亿眠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門碎罚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纳像,你說我怎么就攤上這事荆烈。” “怎么了竟趾?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵憔购,是天一觀的道長。 經(jīng)常有香客問我岔帽,道長玫鸟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任犀勒,我火速辦了婚禮屎飘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贾费。我一直安慰自己钦购,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布褂萧。 她就那樣靜靜地躺著押桃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪导犹。 梳的紋絲不亂的頭發(fā)上唱凯,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音锡足,去河邊找鬼波丰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舶得,可吹牛的內(nèi)容都是我干的掰烟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼沐批,長吁一口氣:“原來是場噩夢啊……” “哼纫骑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起九孩,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤先馆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后躺彬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體煤墙,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梅惯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仿野。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铣减。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脚作,靈堂內(nèi)的尸體忽然破棺而出葫哗,到底是詐尸還是另有隱情,我是刑警寧澤球涛,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布劣针,位于F島的核電站,受9級特大地震影響亿扁,放射性物質(zhì)發(fā)生泄漏捺典。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一魏烫、第九天 我趴在偏房一處隱蔽的房頂上張望辣苏。 院中可真熱鬧,春花似錦哄褒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至骏融,卻和暖如春链嘀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背档玻。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工怀泊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人误趴。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓霹琼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凉当。 傳聞我的和親對象是個(gè)殘疾皇子枣申,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

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