简体   繁体   English

c#犀牛嘲笑 - 这是否适合使用嘲讽?

[英]c# Rhino mocks - Is this an appropriate use of mocks?

Forgive me for my ignorance. 请原谅我的无知。 I'm trying to learn Rhino. 我正在努力学习犀牛。

public Foo(Stream stream)
{
    if (stream == null) throw new ArgumentNullException("woot");
    if (!stream.CanRead) throw new NotSupportedException("sporkish");
    if (!stream.CanSeek) throw new NotSupportedException("monkey");
}

I would like to test this function with a NUnit test by making a test for those exceptions. 我想通过对这些异常进行测试来测试NUnit测试的这个函数。 Is this an appropriate usage of mock objects, or do I actually need to make a special inherited class of Stream? 这是模拟对象的适当用法,还是我真的需要创建一个特殊的继承类Stream? If mocking is appropriate, how do I do this using Rhino? 如果嘲笑是合适的,我该如何使用Rhino? I can figure out how to return dummy values from functions (I think), but not properties. 我可以弄清楚如何从函数(我认为)返回虚拟值,但不是属性。

You can create a mock of Stream which indicates it cannot read and cannot seek, as follows 您可以创建Stream的模拟,指示它无法读取且无法搜索,如下所示

MockRepository mocks = new MockRepository();

Stream mockStream = mocks.StrictMock<Stream>();

Expect.Call(mockStream.CanRead).Return(false);
Expect.Call(mockStream.CanSeek).Return(false);

mocks.ReplayAll();

// Perform the unit test.

mocks.VerifyAll();

A couple of things of worth to remember about mocking: 关于嘲笑的一些值得记住的事情:

  1. Mocking isn't just about creating objects which return dummy values. 模拟不仅仅是创建返回虚拟值的对象。 A good mocking framework tests that a particular member of a class has been accessed. 一个好的模拟框架测试是否已访问类的特定成员。 This lets you test to see that the classes you are testing are making the correct calls to dependant objects. 这使您可以测试以查看正在测试的类正在对依赖对象进行正确调用。 In the above example, if you haven't read the value of both CanRead and CanSeek by the time VerifyAll() is called, an exception will be thrown to fail your test. 在上面的例子,如果你没有看过这两个CanReadCanSeek的时候VerifyAll()被调用时,一个异常将被抛出失败测试。
  2. Mocking is most useful when testing against interfaces. 在对接口进行测试时,模拟最有用。 The less behaviour you can override in a particular type, the less effective mocking becomes. 您可以在特定类型中覆盖的行为越少,模拟效果就越差。 In the case of Stream , you can override the properties you are concerned with, and therefore you can achieve your goal of creating a mock quite easily. 对于Stream ,您可以覆盖您关注的属性,因此您可以轻松实现创建模拟的目标。 If you wanted to mock a non-virtual/overrideable property, you would have a harder task. 如果你想模拟一个非虚拟/可覆盖的属性,你将面临更艰巨的任务。

For your scenario, in order to test the three exceptions are thrown, you will need to create two separate mocks to reach all code paths: one which fails the first assertion ( !stream.CanRead ) and one which passes the first assertion and fails the second assertion ( !stream.CanSeek ). 对于您的场景,为了测试抛出的三个异常,您需要创建两个单独的模拟以到达所有代码路径:一个失败第一个断言( !stream.CanRead ),另一个传递第一个断言并且失败第二个断言( !stream.CanSeek )。

This is an appropriate usage of Mocks. 这是模拟的适当用法。 You would need three Mock objects. 你需要三个模拟对象。 One without stream.CanRead , one without stream.CanSeek , and one with both (to test for success). 一个没有stream.CanRead ,一个没有stream.CanSeek ,一个有两个(为了成功测试)。

Don't forget that this might involve breaking out the functionality of Stream that you're using in to a seperate interface (so that you can build your mock object from the interface). 不要忘记,这可能涉及将您正在使用的Stream功能分解为单独的界面(以便您可以从界面构建模拟对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM