我的情况是我在界面
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的实现的交互始终是相同的。
答案 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),以动态地向模拟对象添加行为。
请注意,您必须修改发布的代码才能使其正常工作: