单元测试模拟Url.Action

时间:2013-03-07 10:06:27

标签: asp.net-mvc-3 unit-testing c#-4.0 moq url.action

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

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

我希望能够在redirectUrl中测试结果,但不知道如何Mock Url.Action.如何设置,以便我可以指定Url.Action("Action", "Controller")叫做归还吗?

1 个答案:

答案 0 :(得分:1)

你做不到。很容易记住关于模拟的规则 - 不能覆盖,不能模拟 1 。如果您派生自Url课程,您是否可以覆盖Action方法?不可以.Moq,Rhino,FakeItEasy或任何其他基于DynamicProxy的框架。

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

  • 使用不同的框架,而不是基于DynamicProxy(通常意味着基于编译器服务进行高级拦截) - 这些工具通常是付费的。
  • 使用interface / delegate包装有问题的调用,并将inject包装到经过测试的代码中(以便您可以使用免费框架进行模拟)

包装怎么样?

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
    });

    // ...
}

通过这样的设置,您可以使用Moq而无需进一步的问题。但是,在单个方法调用中,您也可以使用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 ...