Spring依賴注入與mock

一般使用Spring嘉赎,都會用到依賴注入(DI)。

@Service
public class SampleService {
    @Autowired
    private SampleDependency dependency;
    public String foo() {
        return dependency.getExternalValue("bar");
    }
}

如果測試中需要對Sping注入的對象進行注入蔗崎,該怎么做呢择吊?

選擇一 修改實現(xiàn)

一種做法是把字段注入改為構造函數(shù)注入:

@Service
public class SampleService {
    private SampleDependency dependency;
    @Autowired
    public SampleService(SampleDependency dependency, PersonPoolProvider personPoolProvider) {
        this.dependency = dependency;
    }
}

或者屬性注入:

private SampleDependency dependency;
@Autowired
public void setDependency(SampleDependency dependency) {
    this.dependency = dependency;
}

測試就可以寫成

SampleDependency dependency = mock(SampleDependency.class);
SampleService service = new SampleService(dependency);

從道理來講這樣更加規(guī)范一些。不過事實上會產(chǎn)生更多的代碼攒庵,在字段增刪的時候嘴纺、構造函數(shù)、getter也需要隨之維護叙甸。

選擇二 繞過限制

也可以用一些繞過訪問級別的“黑魔法”颖医,比如測試寫成這樣

SampleDependency dependency = mock(SampleDependency.class);
SampleService service = new SampleService();
ReflectionTestUtils.setField(service, "dependency", dependency);

總感覺不太優(yōu)雅位衩,而且萬一字段改名也很可能漏改裆蒸。

當然,也可以直接把字段改為package可見甚至public糖驴。不過總覺得對不起自己的代碼潔癖僚祷。

選擇三 使用Mockito InjectMocks

這里推薦使用mockito 的InjectMocks注解。測試可以寫成

@Rule public MockitoRule rule = MockitoJUnit.rule();
@Mock SampleDependency dependency;
@InjectMocks SampleService sampleService;

對應于實現(xiàn)代碼中的每個@Autowired字段贮缕,測試中可以用一個@Mock聲明mock對象辙谜,并用@InjectMocks標示需要注入的對象。

這里的MockitoRule的作用是初始化mock對象和進行注入的感昼。有三種方式做這件事装哆。

  • 測試@RunWith(MockitoJUnitRunner.class)
  • 使用rule @Rule public MockitoRule rule = MockitoJUnit.rule();
  • 調用 MockitoAnnotations.initMocks(this),一般在setup方法中調用

InjectMocks可以和Sping的依賴注入結合使用定嗓。比如:

@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest
public class ServiceWithMockTest {
    @Rule public MockitoRule rule = MockitoJUnit.rule();
    @Mock DependencyA dependencyA;
    @Autowired @InjectMocks SampleService sampleService;

    @Test
    public void testDependency() {
        when(dependencyA.getExternalValue(anyString())).thenReturn("mock val: A");
        assertEquals("mock val: A", sampleService.foo());
    }
}

假定Service注入了2個依賴dependencyA, dependencyB蜕琴。上面測試使用Spring注入了B,把A替換為mock對象宵溅。

需要注意的是凌简,Spring test默認會重用bean。如果另有一個測試也使用注入的SampleService并在這個測試之后運行恃逻,那么拿到service中的dependencyA仍然是mock對象雏搂。一般這是不期望的。所以需要用@DirtiesContext修飾上面的測試避免這個問題寇损。

選擇四 Springboot MockBean

如果使用的是Springboot凸郑,測試可以用MockBean更簡單的寫出等價的測試。

@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceWithMockBeanTest {
    @MockBean SampleDependencyA dependencyA;
    @Autowired SampleService sampleService;

    @Test
    public void testDependency() {
        when(dependencyA.getExternalValue(anyString())).thenReturn("mock val: A");
        assertEquals("mock val: A", sampleService.foo());
    }
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矛市,一起剝皮案震驚了整個濱河市芙沥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖憨愉,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烦绳,死亡現(xiàn)場離奇詭異,居然都是意外死亡配紫,警方通過查閱死者的電腦和手機径密,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躺孝,“玉大人享扔,你說我怎么就攤上這事≈才郏” “怎么了惧眠?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長于个。 經(jīng)常有香客問我氛魁,道長,這世上最難降的妖魔是什么厅篓? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任秀存,我火速辦了婚禮,結果婚禮上羽氮,老公的妹妹穿的比我還像新娘或链。我一直安慰自己,他們只是感情好档押,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布澳盐。 她就那樣靜靜地躺著,像睡著了一般令宿。 火紅的嫁衣襯著肌膚如雪叼耙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天掀淘,我揣著相機與錄音旬蟋,去河邊找鬼。 笑死革娄,一個胖子當著我的面吹牛倾贰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拦惋,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼匆浙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了厕妖?” 一聲冷哼從身側響起首尼,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后软能,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迎捺,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年查排,在試婚紗的時候發(fā)現(xiàn)自己被綠了凳枝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡跋核,死狀恐怖岖瑰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砂代,我是刑警寧澤蹋订,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站刻伊,受9級特大地震影響露戒,放射性物質發(fā)生泄漏。R本人自食惡果不足惜娃圆,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一玫锋、第九天 我趴在偏房一處隱蔽的房頂上張望蛾茉。 院中可真熱鬧讼呢,春花似錦、人聲如沸谦炬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽键思。三九已至础爬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吼鳞,已是汗流浹背看蚜。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赔桌,地道東北人供炎。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像疾党,于是被迫代替她去往敵國和親音诫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

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