2017-02-21 180 views
1

我已經實現了基於數組的棧數據結構以及相應的單元測試。這個堆棧實現了我的IStack接口。所以目前,我的UT類看起來像這樣:單元測試中的依賴注入

[TestClass] 
public class Stack_ArrayBased_Tests 
{  
    //check against empty collection 
    [TestMethod] 
    public void IsEmpty_NoElements() 
    { 
     var myStack = new Stack_ArrayBased_Example1(10); 

     var exp = true; 
     var act = myStack.IsEmpty(); 
     Assert.AreEqual(exp, act); 
    } 

現在,我要實現鏈接列表的堆棧。該堆棧將從相同的IStack接口繼承。

我想單元測試鏈表棧。由於兩者都是從相同的接口繼承的,我應該能夠利用已經實現的單元測試,以防止不必要的代碼重複。

什麼是創建兩個獨立的單元測試類,一個是基於陣列堆棧的最佳方式,另一種基於堆棧的鏈表,將使用相同的單元測試方法?我認爲依賴注入將是一個答案,但我會怎麼做呢?

+0

與屬於任何其他代碼,你應該重構代碼這兩種情況都變成了一個自己的類,所以它可以用在不同的用例中。所以,當你已經有*測試用例1的實現時,將行爲重構爲它自己的類,並在兩個測試中使用實例。 – HimBromBeere

回答

2

您可以用另一種方法分隔邏輯。

[TestMethod] 
public void IsEmpty_NoElements_ArrayBased() 
{ 
    var myStack = new Stack_ArrayBased_Example1(10); 
    IsEmpty_NoElements(myStack) 
} 

[TestMethod] 
public void IsEmpty_NoElements_LinkedListBased() 
{ 
    var myStack = new Stack_LinkedListBased_Example1(10); 
    IsEmpty_NoElements(myStack) 
} 

public void IsEmpty_NoElements(IStack myStack) 
{ 
    var exp = true; 
    var act = myStack.IsEmpty(); 
    Assert.AreEqual(exp, act); 
} 
4

當涉及到測試時,依賴注入從來就不是答案。

你是不是測試的抽象,這是不可能的,你測試的具體實現。然而,你可以模擬抽象,接口和抽象類。

您可以創建一些類重用代碼的唯一目的,你從你的測試方法調用類,這是確定的,完全可行的。

您仍然需要兩個測試一個類爲每個具體的實現,並有兩個叫你創建這個新類。這避免了代碼重複。

0

說,我們有以下

public interface IStack 
{ 
    bool IsEmpty { get; } 
} 

public class StackImpl1 : IStack 
{ 
    public StackImpl1(int size) 
    { 
    IsEmpty = true; 
    } 

    public bool IsEmpty { get; } 
} 

public class StackImpl2 : IStack 
{ 

    public StackImpl2(int size) 
    { 
    IsEmpty = true; 
    } 

    public bool IsEmpty { get; } 
} 

而且我們希望實現從OP的IsEmpty_OnCreation()測試。我們可以做一個普通的測試,並添加多個invokers(每個執行測試一個)。問題在於縮放。

對於每個新功能是將待測試我們需要添加

1)測試實施
2)一個調用每個實現的被測試。

對於每一個新的實現我們介紹,我們需要添加一個調用每一個現有的測試。

有可能使用繼承來完成大部分的工作,爲我們

public abstract class StackTest 
{ 
    protected abstract IStack Create(int size); 

    [TestMethod] 
    public void IsEmpty_NoElements() 
    { 
    var myStack = Create(10); 

    var exp = true; 
    var act = myStack.IsEmpty; 
    Assert.AreEqual(exp, act); 

    } 
} 

[TestClass] 
public class StackImp1Fixture : StackTest 
{ 
    protected override IStack Create(int size) 
    { 
    return new StackImpl1(size); 
    } 
} 

[TestClass] 
public class StackImp2Fixture : StackTest 
{ 
    protected override IStack Create(int size) 
    { 
    return new StackImpl2(size); 
    } 
} 

測試在每個派生夾具產生。

如果我們要添加一個新的測試中,我們將它添加到StackTest類,它會自動包含在每個派生夾具。

如果我們添加IStack的第三個實現,我們只需添加一個衍生自StackTest的新測試裝置並重寫create方法。

注:
如果被測類有默認的構造函數,相同的形狀可以用通用StackTest被用作基本

public class GenStackTest<TStack> where TStack : IStack, new() 
{ 

    [TestMethod] 
    public void IsEmpty_NoElements() 
    { 
    var myStack = new TStack(); 

    var exp = true; 
    var act = myStack.IsEmpty; 
    Assert.AreEqual(exp, act); 

    } 
} 

[TestClass] 
public class GenStack1Fixture : GenStackTest<StackImpl1> 
{ 
} 

[TestClass] 
public class GenStack2Fixture : GenStackTest<StackImpl2> 
{ 
}