2017-02-21 151 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> 
{ 
}