【Unit Test】使用Stub破除依賴(二)

/
0 Comments

前言:

接續上一篇提過的 抽取出一個接口,使底層實現可以替換 的重構方法後,這次介紹 "依賴注入(DI):在被測試單元中注入一個偽實現"。


和上一篇的例子相同,只是不同處在於這次在類別中創造一個接口,並將Stub放入接口,至於如何創造接口,就是把抽出來的介面IMemberRepository,透過MemberService類別的建構子注入。
程式碼如下:

//抽取前
public class MemberRepository
{
 public string GetID(string name)
 {
 ....
 }
}

public class MemberService
{
 public string GetMemberID(string name)
 {
  MemberRepository memberrepository = 
      new MemberRepository();
  return memberrepository.GetID(name);
 }
}

//抽取後
public class MemberRepository : IMemberRepository
{
 public string GetID(string name)
 {
 ....
 }
}

public class MemberService
{
 private IMemberRepository _IMemberRepository { get; set; }

 public MemberService(IMemberRepository memberRepository)
 {
  this._IMemberRepository = memberRepository;
 }

 //被測試的方法
 public string GetMemberID(string name)
 {
  return this._IMemberRepository.GetID(name);
 }
}

interface IMemberRepository
{
    string GetID(string name);
}


測試程式碼 :
//Stub
public class FakeMemberRepository : IMemberRepository
{
 public string returnID {get; set;}

 public string GetID(string name)
 {
  return returnID;
 }
}

[TestMethod()]
public void GetMemberID_Test()
{
 //arrange
 var name = "Tom";
 var expected = "321";
 IMemberRepository imr = new FakeMemberRepository();
 imr.returnID = expected;
 MemberService sut = new MemberService(imr);
 
 //act
 var actual = sut.GetMemberID(name);
 
 //assert
 Assert.AreEqual(expected, actual);
}

結語:

這次的範例就是一個完整的測試案例,重點在於如何將你要測試的方法中引用的外部資源隔離。需要注意的是,使用這種建構子注入有可能在越來越多的建構式或是建構式的傳入參數很多就會變得難維護,可讀性也變差,想解決這個問題,可以用一個特殊的類別來包含初始化這個類別所需要的所有值,那你的建構函式就會只需要傳入這個特殊類別參數(Parameter object Refactoring)。
或是使用控制反轉(Inversion of Control, IoC)容器如Unity、Autofac也可以解決這個問題。


You may also like

沒有留言: