无法弄清楚为什么这个 Rhino Mock 失败了?错误:预期为真,但实际为:错误
这是代码:
public interface IAccessPoint
{
int BackHaulMaximum { get; set; }
bool BackHaulMaximumReached();
void EmailNetworkProvider();
}
public class AccessPoint : IAccessPoint
{
public int BackHaulMaximum { get; set; }
public bool BackHaulMaximumReached()
{
if (BackHaulMaximum > 80)
{
EmailNetworkProvider();
return true;
}
return false;
}
public void EmailNetworkProvider()
{
}
}
//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var apMock = MockRepository.GenerateMock<IAccessPoint>();
apMock.Stub(x => x.BackHaulMaximum).Return(81);
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
apMock.AssertWasCalled(x => x.EmailNetworkProvider());
}
Here is the code:
public interface IAccessPoint
{
int BackHaulMaximum { get; set; }
bool BackHaulMaximumReached();
void EmailNetworkProvider();
}
public class AccessPoint : IAccessPoint
{
public int BackHaulMaximum { get; set; }
public bool BackHaulMaximumReached()
{
if (BackHaulMaximum > 80)
{
EmailNetworkProvider();
return true;
}
return false;
}
public void EmailNetworkProvider()
{
}
}
//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var apMock = MockRepository.GenerateMock<IAccessPoint>();
apMock.Stub(x => x.BackHaulMaximum).Return(81);
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
apMock.AssertWasCalled(x => x.EmailNetworkProvider());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我同意tvanfosson的回答。 99%(也许 100%)的情况下,您不会想要为您的 SUT 进行模拟。
然而,它失败的原因是因为您的调用:
不会将导致调用实际方法 BackHaulMaximumReached() !它将调用模拟的方法。
编辑
如果不清楚,这意味着 BackHaulMaximumReached() 将(我认为)返回其返回类型的默认值,在布尔值的情况下为“false”。因此,您需要删除该方法以返回 true 以使 Assert.AreEqual 能够通过(正如我所说,这不是一个好的测试)。
然后您的下一个断言将失败,因为 EmailNetworkProvider() 永远不会被调用(同样,因为您正在调用模拟的方法,而不是实际的 SUT 的方法)。
I agree with tvanfosson's answer. 99% (maybe 100%) of the time, you won't want a mock for your SUT.
However the reason it is failing is because your call:
is not going to result in the actual method BackHaulMaximumReached() being called! It's going to call the mock's method.
Edit
If it wasn't clear, that means that BackHaulMaximumReached() will (I think) return the default value for its return type, which is "false" in the case of bools. So you need to stub out that method to return true to get the Assert.AreEqual to to pass (which is not a good test as I said).
Your next assertion will then fail, as EmailNetworkProvider() will never get called (again, because you are calling the mock's methods, not the actual SUT's methods).
我将更改代码如下:
您所期望的是,给定类的输入,当您调用一个方法时,还会调用另一个会引起一些不需要的副作用的方法。您想要模拟引起副作用的行为,但想要练习其余的实际逻辑。
解决方案是 PartialMock。它允许模拟行为仅应用于您指定的模拟类的成员。您可以在多种语法中使用它,但最安全、最可靠的方法是记录和回放期望,而不是在模拟本身上调用 Expects() 方法。
我们在这里使用它来期望调用我们想要模拟的方法;期望调用将导致实际方法不被调用。然后,执行该类,并使用实际类的逻辑(因此我们测试中的断言成功),但是当到达对我们预期方法的调用时,实际调用的是更新一些内部计数器的模拟方法。然后,VerifyAll() 断言所有期望都按照规定的设置发生。
I would change the code as follows:
What you're expecting is that given the input to the class, when you call a method, another method that induces some unwanted side effects is also called. You want to mock the side-effect-inducing behavior, but you want to exercise the rest of the actual logic.
The solution is a PartialMock. It allows the mocking behavior to be applied to only the members of the mocked class that you specify. You can use it in several syntaxes, but the safest, most reliable method is to record and playback expectations rather than call the Expects() method on the mock itself.
We are using it here to expect a call on our method that we want to mock; expecting the call will cause the actual method not to be called. Then, the class is exercised, and the logic of the actual class is used (hence the assertion in our test succeeds), but when the call to our expected method is reached, what is actually called is the mocked method that updates some internal counters. Then, VerifyAll() asserts that all expectations happened according to the settings prescribed.
您不应该嘲笑您正在测试的类。您应该只模拟被测试类所依赖的类。像这样的东西:
You shouldn't be mocking the class that you are testing. You should only be mocking the classes that class under test depends on. Something like this: