我正在针对依赖IFoo
的MVC控制器编写单元测试。 Foo
(实现)有一种我想要存根的方法,但我想保留其他方法。如何使用RhinoMock
?
Foo
有几个依赖项,我更喜欢而不是来模拟以节省编写额外的代码行并使我的测试混乱。
public interface IFoo{
int Method1();
int Method2();
}
public class Foo : IFoo{
//lot's of dependencies
public Foo(IBar bar, IBaz baz, IStackOverflow so){}
}
[Test]
public void What_I_Have_So_Far(){
//arrange
//load the real IFoo from Ninject (DI)
var mockFoo = new Ninject.Kernel(new MyExampleModule())
.Get<IFoo>();
//I want this test to use the real Method1, but not Method2
//so stub Method2
mockFoo
.Stub(x => x.Method2()) //<---- blows up here
.Returns(42);
//act
var controllerUnderTest = new Controller(mockFoo);
使用这种方法,RhinoMock会抛出异常:
System.InvalidOperationException:对象&#39; MyApplication.MyExampleModule&#39;不是一个嘲弄的对象。
如何存根method2
?
我知道我可以通过IFoo
创建MockRepository.GenerateMock
作为模拟,但是之后我必须复制Method1
的真实实现。
Brad和Jimmy的解决方案同样适用,我选择Brad只是因为写代码较少。
然而,在进一步研究之后,看起来我需要的是AutoMocker。接缝是StructureMap和Moq的接缝,但不是RhinoMocks:https://github.com/RhinoMocks/RhinoMocks/issues/3
答案 0 :(得分:1)
你必须以相反的方式做到这一点。创建模拟IFoo
并将某些调用重定向到真实IFoo
(这必须通过WhenCalled
扩展名完成):
var realFoo = new Ninject.Kernel(new MyExampleModule()).Get<IFoo>();
var mockFoo = MockRepository.GenerateStub<IFoo>();
mockFoo.Stub(f => f.Method2()).Return(42);
mockFoo.Stub(f => f.Method1())
.WhenCalled(invocation =>
{
invocation.ReturnValue = realFoo.Method2();
})
.Return(whateverValue);
最后Return
是必需的,即使我们之前覆盖了几行。否则Rhino会抛出异常。
答案 1 :(得分:1)
由于需要最少量的“侵入式”工作,我会考虑使用适配器模式。所以,我们有原始的界面和具体的类:
public interface IFoo
{
void Method1();
void Method2();
}
public class Foo : IFoo
{
public void Method1()
{
Console.WriteLine("I am Method1 of Foo");
}
public void Method2()
{
Console.WriteLine("I am Method2 of Foo");
}
}
用于单元测试的单个实现:
public class FooAdapter : IFoo
{
private readonly IFoo foo;
public FooAdapter(IFoo foo)
{
this.foo = foo;
}
public void Method1()
{
this.foo.Method1();
}
public void Method2()
{
Console.WriteLine("I am Method2 of FooAdapter");
}
}
该类可以是单元测试类的本地类,只需定义为:
IFoo foo = new FooAdapter(kernel.Get<IFoo>());
我同意你的意见,更改基本代码以满足单元测试并不是正确的选择。单元测试应该随便坐在上面,永远不要反向探测他们所针对的代码。
答案 2 :(得分:1)
然而,在进一步研究之后,它看起来像我 需要的是一个AutoMocker。有接缝是StructureMap和Moq的接缝, 但不是RhinoMocks:https://github.com/RhinoMocks/RhinoMocks/issues/3
我没有深入研究过,但我知道CodePlex上的AutoMock项目。也许这就是答案?
功能强>