2

我正在使用 Moq 框架编写单元测试,并且我有一个返回的控制器函数

return Json(new
{    
    redirectUrl = Url.Action("Action", "Controller"),
    isredirection = true
});

我希望能够测试结果,redirectUrl但不知道如何设置MockUrl.Action.以便我可以指定是否Url.Action("Action", "Controller")调用返回这个?

4

1 回答 1

1

你不能。关于模拟的规则很容易记住 -不能覆盖,不能模拟1。如果你是从类派生的Url,你能覆盖Action方法吗?不可以。Moq、Rhino、FakeItEasy 或任何其他基于 DynamicProxy 的框架也不能。

您的选择范围缩小了以下范围:

  • 使用不同的框架,而不是基于 DynamicProxy(这通常意味着基于编译器服务进行高级拦截)——这些工具通常是付费的。
  • 用接口/委托包装有问题的调用并将其注入测试代码(以便您可以使用免费框架模拟它)

包装会是什么样子?

public interface IUrlWrapper
{
    string Action(string name, object values);
}

// Wrapper Interface
public class TestedClass
{
    private readonly IUrlWrapper url;

    public TestedClass(IUrlWrapper urlWrapper)
    {
        this.url = urlWrapper;
    }

    // ...

    return Json(new
    {
        redirectUrl = this.url.Action("Action", "Controller"),
        isredirection = true
    });

    // ...
}

通过这样的设置,您可以毫无问题地使用起订量。但是,在单个方法调用中,您也可以在Func没有任何隔离框架的情况下使用委托:

// Func Delegate
public class TestedClass
{
    private readonly Func<string, object, string> urlAction;

    public TestedClass(Func<string, object, string> urlAction)
    {
        this.urlAction = urlAction;
    }

    // ...

    return Json(new
    {
        redirectUrl = this.urlAction("Action", "Controller"),
        isredirection = true
    });

    // ...
}

在您的测试中,您只需动态创建委托。


1 我写了一篇博文,更详细地介绍了这个问题:How to mock private method with ...

于 2013-03-07T11:08:54.643 回答