Machine.Fakes如何测试虚拟方法实现?

时间:2012-03-23 14:51:56

标签: c# mocking mspec automocking machine.fakes

鉴于我有一个控制器类:

public class ResourceController : AuthorizedController
{      
    public virtual string Resource()
    {
         //do magic
    }

    public virtual string ResourceParent()
    {
        var url = Resource();
        return url;
    }
}

}

使用测试工具:

[Subject(typeof (ResourceController))]
public class When_I_want_the_parent_resource : WithSubject<ResourceController>
{
    private static readonly string ParentUrl = "/organizations/1";
    private static readonly string ResourceUrl = "/organizations/1/contacts/1";
    private static string _result;

    private Establish context = () =>
                                    {
                                        The<ResourceController>()
                                            .WhenToldTo(x => x.Resource())
                                            .Return(ResourceUrl);
                                    };

    private Because of = () => _result = Subject.ResourceParent();

    private It should_match_the_expected_parent_url = () =>
                             _result.ShouldEqual(ParentUrl);
}

此单元测试将失败,因为Subject.ResourceParent()将返回null,因为Machine.Fakes已自动插入此方法。作为临时解决方法,我刚刚从ResourceParent中删除了虚拟关键字,以便能够测试我的代码。我认为必须有一个真正的解决方案让我告诉Machine.Fakes不要覆盖ResourceParent()

3 个答案:

答案 0 :(得分:3)

实际上在Machine.Fakes中没有“真正的”解决方案。我认为你需要重新考虑你的夹具设计。

首先,正如蒂姆已经指出的那样,你不应该伪造任何关于这个主题的方法。相反,您应该伪造控制器的依赖关系并按规范使用控制器。 “The”方法的预期用法是访问规范中主题的依赖关系,但您在规范中尝试的是访问主题本身。我认为那是出问题的地方。 &lt; ResourceController&gt;和主题实际上是单独的实例。这就是为什么配置交互不会发生的原因。

只需在代码中解决此问题的一些选项:

  • 在您的代码中引入一个新的依赖项,您可以通过“The”
  • 来存根
  • 如果第一个似乎是重量级的,你也可以用Func&lt; string&gt;替换虚方法。控制器的依赖关系,并使用“配置”方法为规范注入特定规范。

HTH,

比约恩

答案 1 :(得分:2)

如果您正在测试控制器,那么也许您不应该创建该控制器的模拟或伪造 。否则你只是测试一个模拟而且测试确实没有任何效力。

模拟或伪造控制器的依赖项。测试真实的控制器。

答案 2 :(得分:0)

最后,我最终将这个测试从Machine.Fakes中拉出来并将其放入常规单元测试中。然后我直接使用Moq来配置HttpRequestBase种子数据,然后手动创建我的控制器类并调用它上面的方法。