rhino mock一个接口IA,它用抽象类aB实现接口IB

时间:2014-06-20 11:32:02

标签: c# .net unit-testing abstract-class rhino-mocks

我的情况是我在界面

public interface IA : IB
{
}

其中

public interface IB
{
    List<string> Errors{get;}
    void AddError(string error);
}

带有抽象类

public abstract class B
{
    private List<string> errors = new List<string>();
    public List<string> Errors{get{return errors;}}
    public void AddError(string error)
    {
        if (!errors.Contains(error)) 
            errors.Add(error);
    }        
}

我在另一个类上有一个方法,如:

public class MyClass
{
    public void MyMethod(IA obj)
    {            
        obj.AddError("some string");
    }
}

然后我有一个单元测试,我想通过传入一个存根的IA来测试MyClass做了它应该做的事情:

public void Test()
{
    var sut = new MyClass();
    var input = MockRepository.GenerateStub<IA>();
    sut.MyMethod(input);
    Assert.AreEqual(1, input.Errors.Count);
}

但是当涉及到断言时,Errors为null,因为基类B没有包含在IA的存根中,有没有办法指定我希望IBs的实现由abtsract类提供而不需要创建一个派生自B?

的具体类

我已经错过了一些细节,但我会扩展说有一组接口,比如所有实现IB的IA,以及一组像MyClass这样的类,每个接受不同的接口,MyMethod的细节取决于在它接受的接口IA上,但与IB的实现的交互始终是相同的。

2 个答案:

答案 0 :(得分:0)

一种可能的解决方案是创建IA的抽象实现

public abstract class A : B, IA
{
    //abstract implementations of all properties and methods on IA, nothing concrete
}

然后可以在单元测试中删除它:

public void Test()
{
    var sut = new MyClass();
    var input = MockRepository.GenerateStub<A>();
    sut.MyMethod(input);
    Assert.AreEqual(1, input.Errors.Count);
}

并且A上的属性和方法需要被抄(或嘲笑)。

这确实意味着一个额外的阶级需要在IA的静脉中存在每个界面,这远非理想,但它是我现在看到的这种方式。

答案 1 :(得分:0)

界面代表行为契约。它本质上不与任何实现相结合。你想要的是一个模拟对象,它携带由B类定义的行为(换句话说,你需要一个模拟的B对象),同时实现IA。

您可以使用multi,partial mock来实现它:

var sut = new MyClass();
var input = MockRepository.GeneratePartialMock<B, IA>();
sut.MyMethod((IA)input);
Assert.AreEqual(1, input.Errors.Count);

GeneratePartialMock是模拟已经定义了某些行为的类的方法。基本上它使您能够重写(存根)类中定义的覆盖方法。如果您没有存根方法,则会调用原始行为。

您可以在类型参数列表中包含更多接口(在您的情况下为IA),以动态地向模拟对象添加行为。

请注意,您必须修改发布的代码才能使其正常工作:

  1. 应在接口IB
  2. 中定义Initialize()
  3. 方法应在B类中定义为虚拟