我有以下需要进行单元测试的类结构:
public interface IFoo
{
int Value { get;}
int GetValue();
}
public class BaseClass : IFoo
{
public virtual int Value { get { return 100; } }
public virtual int GetValue()
{
return Value;
}
}
public class ChildClass : BaseClass, IFoo
{
public override int GetValue()
{
return Value;
}
}
我正在尝试使用 RhinoMocks 测试 ChildClass.GetValue() 方法。
我有以下 stub 代码:
public ChildClass CreateChildClass(int value)
{
var childClass = MockRepository.GenerateStub<ChildClass>();
childClass.Stub(x => x.Value).Return(value);
return childClass;
}
以及以下单元测试代码:
public IEnumerable<IFoo> CreateList()
{
yield return CreateChildClass(1000);
yield return CreateChildClass(2000);
}
[TestMethod]
public void virtualMethodTest()
{
var list = CreateList();
var query = from p in list
select p.GetValue(); //I can't use p.Value
var sum = query.Sum(p => p);
}
手头的问题是总和始终为零。我可以快速查看列表并查看两个具有来自 CreateList() 的正确值的模拟对象。
是否可以对子类的虚方法进行单元测试?还是我需要使用不同的 RhinoMocks 方法?
谢谢
最佳答案
两件事:
- 您正在创建具体类的 stub ,而不是 IFoo。模拟在其内部工作中具有高度反射(reflect)性,因此多态调用的行为可能相同也可能不同,具体取决于框架和调用的确切性质。
- 您正在创建 stub , stub 本质上会忽略对其接口(interface)进行的任何非预期调用(返回返回类型的默认值)。这是您问题的直接原因; GetValue() 不是预期的,因此它返回默认整数值 (0)。
您要测试实际类的某些行为,但要覆盖某些其他行为(副作用,不属于测试范围的一部分,等等)。 RhinoMocks 中的基本答案是 PartialMock,它将默认为实际类的行为,除非您希望进行特定调用。因此,不是 GenerateStub<>(),而是创建 MockRepository 的实例并实例化一个新的 MockRepository.PartialMock()。期望您要覆盖的内部行为,但不要触及任何其他内容。您可能不得不使用较旧的录制和播放方法;当您实例化 PartialMock 然后在该实例上调用 Expect() 时,我通常使用的 RhinoMocks 版本的行为不正确。
更改将遵循以下原则:
//instantiate Mocks in class scope, as an instance of MockRepository
public ChildClass CreateChildClass(int value)
{
var childClass = Mocks.PartialMock<ChildClass>();
childClass.Expect(x => x.Value).Return(value);
return childClass;
}
关于c# - Linq 中的单元测试虚拟方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3729638/