Mock 框架与 MS Fakes 框架 [英] Mock framework vs MS Fakes frameworks

查看:26
本文介绍了Mock 框架与 MS Fakes 框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对 NMock 与 VS 2011 Fakes Framework 等 Mock 框架的差异有点困惑.通过 MSDN,我了解到 Fakes 允许您像 RhinoMock 或 NMock 一样模拟您的依赖项,但是方法不同,Fakes 生成代码来实现此功能,但 Mocks 框架没有.那么我的理解正确吗?Fakes 只是另一个 Mock 框架

A bit confused on the differences of Mock frameworks like NMock vs the VS 2011 Fakes Framework. Going through MSDN, what I understand is that Fakes allow you to mock your dependencies just like RhinoMock or NMock, however the approach is different, Fakes generates code to achive this functionality but Mocks framework does not. So is my understanding correct? Is Fakes just another Mock framework

推荐答案

您的问题是关于 MS Fakes 框架与 NMock 有何不同,似乎其他答案已经解决了其中的一些问题,但这里有更多关于如何解决的信息它们是相同的,它们又有何不同.NMock 也类似于 RhinoMocks 和 Moq,所以我将它们与 NMock 归为一组.

Your question was about how the MS Fakes framework is different from NMock and it appears the other answers have resolved some of that, but here is some more information regarding how they are the same and how they are different. NMock is also similar to RhinoMocks and Moq, so I'm grouping them in with NMock.

我认为 NMock/RhinoMocks/Moq 和 MS Fakes 框架之间有 3 个主要区别:

There are 3 major differences I see right off between NMock/RhinoMocks/Moq and the MS Fakes Framework:

  • MS fakes 框架使用生成的代码,很像早期版本的 Visual Studio 中的访问器,而不是泛型类型.当您想对依赖项使用 fakes 框架时,将包含该依赖项的程序集添加到测试项目的引用中,然后右键单击它以生成测试替身(存根或垫片).然后,当您进行测试时,您实际上是在使用这些生成的类.NMock 使用泛型来完成同样的事情(即 ISudentRepository studentRepository = mocks.NewMock()).在我看来,MS Fakes 框架方法禁止在测试中进行代码导航和重构,因为您实际上是针对生成的类,而不是您的真实界面.

  • The MS fakes framework uses generated code, much like Accessors in prior versions of Visual Studio instead of generic types. When you want to use the fakes framework for a dependency, you add the assembly that contains the dependency to the references of the test project and then right-click on it to generate the test doubles (stubs or shims). Then when you are testing, you are actually using these generated classes instead. NMock uses generics to accomplish the same thing (i.e. IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()). In my opinion, the MS Fakes framework approach inhibits code navigation and refactoring from within the tests since you are actually working against a generated class, not your real interface.

MS fakes 框架提供存根和痣(垫片),而 NMock、RhinoMocks 和 Moq 都提供存根和模拟.我真的不理解 MS 决定不包括模拟,而且我个人不是痣的粉丝,原因如下所述.

The MS fakes framework supplies stubs and moles (shims), whereas NMock, RhinoMocks, and Moq all provide stubs and mocks. I really don't understand MS's decision to not include mocks and I am, personally not a fan of moles for reasons described below.

使用 MS fakes 框架,您可以提供要存根的方法的替代实现.在这些替代实现中,您可以指定返回值并跟踪有关如何或是否调用方法的信息.使用 NMock、RhinoMocks 和 Moq,您可以生成一个模拟对象,然后使用该对象来指定存根返回值或跟踪交互(是否以及如何调用方法).我发现 MS fakes 方法更复杂,表达能力也更差.

With the MS fakes framework, you supply an alternative implementation of the methods you want to stub. Within these alternate implementations, you can specify the return values and track information about how or if the method was called. With NMock, RhinoMocks and Moq, you generate a mock object and then use that object to specify stubbed return values or to track interactions (whether and how the methods were called). I find the MS fakes approach more complex and less expressive.

澄清框架提供的区别:NMock、RhinoMocks 和 Moq 都提供两种类型的测试替身(存根和模拟).fakes 框架提供了存根和痣(他们称之为垫片),不幸的是不包括模拟.为了理解 NMock 和 MS Fakes 之间的异同,了解这些不同类型的测试替身是什么会很有帮助:

To clarify the difference in what the frameworks provide: NMock, RhinoMocks and Moq all provide two types of test doubles (stubs and mocks). The fakes framework provides stubs and moles (they call them shims), and unfortunately does not include mocks. In order to understand the differences and similarities between NMock and MS Fakes, it is helpful to understand what these different types of test doubles are:

存根:当您需要为方法或属性提供值时,将使用存根,这些值将被被测方法询问您的测试替身.例如,当我的被测方法调用 IStudentRepository 测试替身的 DoesStudentExist() 方法时,我希望它返回 true.

Stubs: Stubs are used when you need to provide a values for methods or properties that will be asked of your test doubles by the method under test. For example, when my method under test calls the DoesStudentExist() method of the IStudentRepository test double, I want it to return true.

NMock 和 MS fakes 中存根的想法是相同的,但是使用 NMock 你会做这样的事情:

The idea of stubs in NMock and MS fakes is the same, but with NMock you would do something like this:

Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));

使用 MSFakes 你会做这样的事情:

And with MSFakes you would do somethign like this:

IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
    DoesStudentExistInt32 = (studentId) => { return new Student(); }
};

请注意,在 MS Fakes 示例中,您为DoesStudentExist 方法创建了一个全新的实现(请注意,它被称为DoesStudentExistInt32,因为 fakes 框架在生成存根对象时将参数数据类型附加到方法名称中,我认为这掩盖了测试的清晰度).老实说,NMock 实现也让我感到困扰,因为它使用字符串来标识方法名称.(如果我误解了 NMock 的用途,请原谅我.)这种方法确实抑制了重构,因此我强烈推荐 RhinoMocks 或 Moq 而不是 NMock.

Notice in the MS Fakes example you create an entirely new implementation for the DoesStudentExist method (Note that it is called DoesStudentExistInt32 because the fakes framework appends the parameter data types to the method names when it generates the stub objects, I think this obscures the clarity of the tests). To be honest the NMock implementation also bugs me because it uses a string to identify the method name. (Forgive me if I've misunderstood how NMock is intended to be used.) This approach really inhibits refactoring and I'd highly recommend RhinoMocks or Moq over NMock for this reason.

Mocks:Mocks 用于验证被测方法与其依赖项之间的交互.使用 NMock,您可以通过设置与此类似的期望来实现:

Mocks: Mocks are used to verify interaction between your method under test and its dependencies. With NMock, you do this by setting expectations similar to this:

Expect.Once.On(mockStudentRepository).Method("Find").With(123);

这是为什么我更喜欢 RhinoMocks 和 Moq 而不是 NMock 的另一个原因,NMock 使用旧的期望样式,而 RhinoMocks 和 Moq 都支持排列/行为/断言方法,您可以在该方法的末尾将预期的交互指定为断言像这样测试:

This is another reason why I'd prefer RhinoMocks and Moq over NMock, NMock uses the older expectation style whereas RhinoMocks and Moq both support the Arrange/Act/Assert approach where you specify you expected interactions as assertions at the end of the test like this:

stubStudentRepository.AssertWasCalled( x => x.Find(123));

再次注意,RhinoMocks 使用 lambda 而不是字符串来标识方法.ms fakes 框架根本不提供模拟.这意味着在您的存根实现中(请参阅上面的存根描述),您必须设置稍后验证是否正确设置的变量.看起来像这样:

Again, note that RhinoMocks uses a lambda instead of a string to identify the method. The ms fakes framework does not provide mocks at all. This means that in your stubbed out implementations (see the description of stubs above) you have to set variables that you later verify were set correctly. That would look something like this:

bool wasFindCalled = false;

IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() 
{
    DoesStudentExistInt32 = (studentId) => 
        { 
            wasFindCalled = true;
            return new Student(); 
        }
};

classUnderTest.MethodUnderTest();

Assert.IsTrue(wasFindCalled);

我发现这种方法有点复杂,因为您必须在存根中跟踪调用,然后在稍后的测试中对其进行断言.我发现 NMock,尤其是 RhinoMocks,示例更具表现力.

I find this approach to be a little convoluted since you have to track the call up in the stub and then assert it later in the test. I find the NMock, and especially the RhinoMocks, examples to be more expressive.

痣 (Shims): 坦率地说,我不喜欢痣,因为它们可能被滥用.我非常喜欢单元测试(尤其是 TDD)的一件事是测试你的代码可以帮助你了解你在哪里编写了糟糕的代码.这是因为测试写得不好的代码很困难.使用痣时并非如此,因为痣实际上旨在允许您测试未注入的依赖项或测试私有方法.它们的工作方式与存根类似,不同之处在于您像这样使用 ShimsContext:

Moles (Shims): To be frank, I do not like moles, because of their potential for misuse. One of the things I like so much about unit testing (and TDD in particular) is that testing your code helps you to understand where you have written poor code. This is because testing poorly written code is difficult. This is not true when using moles because moles are actually designed to allow you to test against dependencies that are not injected or to test private methods. They work similarly to stubs, except that you use a ShimsContext like this:

using (ShimsContext.Create())
{
    System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}

我对 shims 的担忧是人们会开始将它们视为一种更简单的单元测试方法",因为它不会强迫您按照应有的方式编写代码.有关此概念的更完整的文章,请参阅我的这篇文章:

My worry with shims is that people will start seeing them as "an easier way to unit test" because it doesn't force you to write code the way you should. For a more complete write-up on this concept see this post of mine:

有关与假框架相关的一些问题的更多信息,请查看以下帖子:

For more information on some concerns related to the fakes frameworks take a look at these posts:

如果您对学习 RhinoMocks 感兴趣,这里有一个 Pluralsight 培训视频(完全披露 - 我编写了这门课程并获得了付费使用费,但我认为它适用于本次讨论,因此我将其包括在此处):

If you're interested in learning RhinoMocks here's a Pluralsight training video (full disclosure - I wrote this course and get paid royalties for views, but I think it applies to this discussion so I'm including it here):

这篇关于Mock 框架与 MS Fakes 框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆