0

鉴于我有一个控制器类:

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 中删除了 virtual 关键字,以便能够测试我的代码。我认为必须有一个真正的解决方案让我告诉 Machine.Fakes 不要覆盖ResourceParent()

4

3 回答 3

3

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

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

只有一些选项可以在您的代码中解决此问题:

  • 在您的代码中引入一个新的依赖项,您可以通过“The”存根
  • 如果第一个似乎重量级,您还可以将虚拟方法替换为控制器的 Func<string> 依赖项,并使用“配置”方法为您的规范注入特定于规范的规范。

高温下,

比约恩

于 2012-03-25T12:59:15.403 回答
2

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

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

于 2012-03-23T23:56:14.463 回答
0

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

于 2012-03-29T12:54:46.747 回答