【Unit Test】使用Stub破除依賴(一)
/
0 Comments
打破依賴的重構方法分為兩類,我們分別稱為A型和B型重構,兩者相互依賴:
A: 把具體的類別抽象成接口(interfaces)或是委派(delegates)。
- 抽取出一個接口,使底層實現可以替換
B: 重構代碼,藉由重構來產生能注入這種委派和接口的偽實現(fake implementation)。
- 在被測試類別中注入一個Stub實體
- 在建構子注入一個偽對象
- 注入一個作為屬性設置和讀取的偽對象
- 在一個方法呼叫前,注入一個偽對象
先來介紹 "抽取出一個接口,使底層實現可以替換" :
簡單來說,就是將方法從類別中提取成介面。
舉個例,想測試MemberService的GetMemberID方法,先將這個方法用到的外部資源MemberRepository隔離開來,抽成介面IMemberRepository,接著就可以用這個介面當接口
程式碼如下:
返回固定值的簡單Stub程式碼如下:
A: 把具體的類別抽象成接口(interfaces)或是委派(delegates)。
- 抽取出一個接口,使底層實現可以替換
B: 重構代碼,藉由重構來產生能注入這種委派和接口的偽實現(fake implementation)。
- 在被測試類別中注入一個Stub實體
- 在建構子注入一個偽對象
- 注入一個作為屬性設置和讀取的偽對象
- 在一個方法呼叫前,注入一個偽對象
先來介紹 "抽取出一個接口,使底層實現可以替換" :
簡單來說,就是將方法從類別中提取成介面。
舉個例,想測試MemberService的GetMemberID方法,先將這個方法用到的外部資源MemberRepository隔離開來,抽成介面IMemberRepository,接著就可以用這個介面當接口
程式碼如下:
//抽取前
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
{
//被測試的方法
public string GetMemberID(string name)
{
IMemberRepository imr = new MemberRepository();
return imr.GetID(name);
}
}
interface IMemberRepository
{
string GetID(string name);
}
返回固定值的簡單Stub程式碼如下:
//Stub
public class FakeMemberRepository : IMemberRepository
{
public string GetID(string name)
{
return "123";
}
}
//引用Stub
public string GetMemberID(string name)
{
IMemberRepository imr = new FakeMemberRepository();
return imr.GetID(name);
}