Unit testing 如何使用Rhino Mock模拟本地函数调用?
以下是我的情况: 我想测试“HasSomething()”函数,它位于以下类中:Unit testing 如何使用Rhino Mock模拟本地函数调用?,unit-testing,rhino-mocks,Unit Testing,Rhino Mocks,以下是我的情况: 我想测试“HasSomething()”函数,它位于以下类中: public class Something { private object _thing; public virtual bool HasSomething() { if (HasSomething(_thing)) return true; return false; } p
public class Something
{
private object _thing;
public virtual bool HasSomething()
{
if (HasSomething(_thing))
return true;
return false;
}
public virtual bool HasSomething(object thing)
{
....some algo here to check on the object...
return true;
}
}
所以,我写我的测试是这样的:
public void HasSomethingTest1()
{
MockRepository mocks = new MockRepository();
Something target = mocks.DynamicMock(typeof(Something)) as Something;
Expect.Call(target.HasSomething(new Object())).IgnoreArguments().Return(true);
bool expected = true;
bool actual;
actual = target.HasSomething();
Assert.AreEqual(expected, actual);
}
我的试卷写对了吗?
请帮助我,因为我甚至不能得到预期的结果。“HasSomething(object)”不能用那种方式来模仿。它没有将我的期望值设置为“真”
谢谢。回应OP的“答案”:您的主要问题是Rhinomock不会模拟类的成员,而是创建模拟类,然后我们可以为其成员(即属性和函数)设置期望和固定响应。如果您试图测试mock/stub类的成员函数,那么您将面临测试mock框架而非实现的风险 对于逻辑路径依赖于本地(通常是私有)函数的返回值的特定场景,您确实需要一个外部依赖项(另一个对象),它将影响您从该本地函数所需的返回值。对于上面的代码片段,我将编写如下测试:
[Test]
public void TestHasSomething()
{
// here I am assuming that _thing is being injected in via the constructor
// you could also do it via a property setter or a function
var sut = new Something(new object());
Assert.IsTrue(sut.HasSomething);
}
i、 e.无需模拟
这是我过去常常对嘲弄产生的误解之一;我们模拟被测系统(SUT)的依赖关系的行为。类似于:SUT调用了几个依赖性方法,模拟过程提供了固定的响应(而不是去数据库等)来指导逻辑的流动方式 下面是一个简单的示例(注意,我在这个测试中使用了RhinoMocks AAA语法。顺便说一句,我注意到您在代码示例中使用的语法使用了Record Replay范例,只是它没有使用Record and Replay!这可能也会导致问题):
公共类SUT
{
依赖性
公共SUT(依赖关系)
{
_依赖=依赖;
}
...
public int MethodUnderTest()
{
如果(_depend.IsReady)
返回1;
其他的
返回-1;
}
}
...
[测试]
公共void TestSUT_MethodUnderTest()方法
{
var dependency=MockRepository.GenerateMock();
dependency.Stub(d=>d.IsReady).Return(true);
var sut=新sut(依赖项);
Assert.AreEqual(1,sut.MethodUnderTest());
}
所以你的问题是,你试图测试一个模拟对象的行为。这意味着你根本没有在测试你的类 在这种情况下,test double应该是类某物的派生版本。然后重写HasSomething(object)方法并确保HasSomething()调用您的方法 如果我理解正确,您实际上对测试方法HasDynamicFlow(上面的示例中没有描述)感兴趣,而不关心HasSomething的算法 Preet是正确的,因为您可以简单地对某个对象进行子类化,并覆盖HasSomething的行为以使算法短路,但这需要创建一些额外的测试伪代码,Rhino可以有效地消除这些代码 考虑使用动态模拟而不是动态模拟。存根没有那么严格,非常适合处理属性。然而,这些方法需要一些额外的努力
[Test]
public void CanStubMethod()
{
Foo foo = MockRepository.GenerateStub<Foo>();
foo.Expect(f => f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething(null)).IgnoreArguments().Return(true);
Assert.IsTrue(foo.HasDynamicFlow());
}
[测试]
公共方法()
{
Foo-Foo=MockRepository.GenerateStub();
Expect(f=>f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.noexpection);
foo.Expect(f=>f.HasSomething()).CallOriginalMethod(OriginalCallOptions.noexpection);
Expect(f=>f.HasSomething(null)).IgnoreArguments().Return(true);
Assert.IsTrue(foo.HasDynamicFlow());
}
编辑:添加代码示例并将部分模拟切换为存根如jpoh所说,模拟对象应传递到SUT中。某物,某物(mockedObject);
[Test]
public void CanStubMethod()
{
Foo foo = MockRepository.GenerateStub<Foo>();
foo.Expect(f => f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething(null)).IgnoreArguments().Return(true);
Assert.IsTrue(foo.HasDynamicFlow());
}