使用RhinoMock或Moq测试方法的内部 [英] Testing the internals of a method with RhinoMock or Moq

查看:102
本文介绍了使用RhinoMock或Moq测试方法的内部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于这个可笑的东西来说,这是很新的,我有几个问题.

Quite new to this mocking thing, I have a couple of questions.

如果我错了,请纠正我: 模拟不会初始化真正的方法,即模拟实际上不会调用您的类的构造函数.相反,它的作用类似于查看类的签名并创建具有该签名但不具有方法功能的对象.如果您只需要该类型的对象但又不想测试其内部结构,例如,这很有用.如果您实际测试的对象对此有依赖性.

Correct me if I'm wrong: Mocking does not initialize the real method i.e. Mocking will not actually call the constructor of your class. Instead it does something like look at the signature of the class and create an object with that signature but with none of the methods functionality. This is useful if you just need an object of that type but don't want to test it's internals, e.g. if the object you're actually testing has a dependency on it.

我正在尝试测试方法的内部,这是否意味着我必须创建该方法所属的类的实例?

I'm trying to test the internals of a method, does this mean I must create an instance of the class that the method belongs to?

推荐答案

摘要:动态模拟不会帮助您测试类型的内部,但是您不应该尝试在第一名.

Summary: Dynamic mocks will not help you testing the internals of your types, but you shouldn't be attempting to do that in the first place.

您的描述基本上是正确的,但是要复杂得多.本质上,动态模拟不会做您无法手工完成的任何事情.

You are basically correct in your description, but it's a bit more complicated than that. Essentially, dynamic mocks don't do anything you couldn't do by hand.

假设您正在针对此类接口进行编程:

Let's say you are programming against an interface such as this one:

public interface IMyInterface
{
    string Foo(string s);
}

您可以手动创建IMyInterface的特定于测试的实现,该实现将忽略输入参数并始终返回相同的输出:

You could manually create a test-specific implementation of IMyInterface that ignores the input parameter and always returns the same output:

public class MyClass : IMyInterface
{
    public string Foo(string s)
    {
        return "Bar";
    }
}

但是,如果您要测试使用者对不同返回值的反应方式,那么该操作很快就会重复出现,因此您可以使用一个框架来动态创建它们,而不用手动编写 Test Doubles 为你.

However, that becomes repetitive really fast if you want to test how the consumer responds to different return values, so instead of coding up your Test Doubles by hand, you can have a framework dynamically create them for you.

想象一下,动态模拟实际上编写的代码类似于上面的MyClass实现(它们实际上并没有编写代码,而是动态地发出类型,但这是一个足够准确的类比).

Imagine that dynamic mock really write code similar to the MyClass implementation above (they don't actually write the code, they dynamically emit the types, but it's an accurate enough analogy).

在这里,您可以使用Moq定义与MyClass相同的行为:

Here's how you could define the same behavior as MyClass with Moq:

var mock = new Mock<IMyInterface>();
mock.Setup(x => x.Foo(It.IsAny<string>())).Returns("Bar");

在两种情况下,创建对象时都会调用所创建类的构造函数.由于接口没有构造函数,因此通常是默认的构造函数(分别是MyClass和动态发出的类).

In both cases, the construcor of the created class will be called when the object is created. As an interface has no constructor, this will normally be the default constructor (of MyClass and the dynamically emitted class, respectively).

您可以对像这样的具体类型做同样的事情:

You can do the same with concrete types such as this one:

public class MyBase
{
    public virtual string Ploeh()
    {
        return "Fnaah";
    }
}

通过手工,您将能够从MyBase派生并重写Ploeh方法,因为它是虚拟的:

By hand, you would be able to derive from MyBase and override the Ploeh method because it's virtual:

public class TestSpecificChild : MyBase
{
    public override string Ploeh()
    {
        return "Ndøh";
    }
}

动态模拟库可以做到这一点,抽象方法也是如此.在这种情况下,将调用基类的构造函数 ,因为.NET就是这样.

A dynamic mock library can do the same, and the same is true for abstract methods. In this case, the base class' constructor will be invoked, because that's how .NET works.

但是,您不能编写覆盖非虚拟或内部成员的代码,动态模拟也不能.他们只能做您可以手工做的事情.

However, you can't write code that overrides a non-virtual or internal member, and neither can dynamic mocks. They can only do what you can do by hand.

不过,有一条建议:仅通过公共API对内部成员进行单元测试.

注意:上面的描述对于大多数动态模拟都是正确的,但TypeMock除外,它是不同的,而且...令人恐惧.

Caveat: The above description is true for most dynamic mocks with the exception of TypeMock, which is different and... scary.

这篇关于使用RhinoMock或Moq测试方法的内部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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