你是如何生活在App_GlobalResource中的Moq ares?

时间:2012-10-22 14:00:40

标签: .net asp.net-mvc-3 unit-testing moq app-globalresources

我正在为MVC3 Web项目中的控制器编写单元测试,但是我的测试在尝试访问这样的资源时会抛出异常:

return Index(Resources.Strings.MyStringResource);

该资源是.resx文件,标题为Strings

我正在使用Moq库来实现HttpContextBase功能的单元测试,所以我想知道如何使用Moq库来访问App_GlobalResource。

非常感谢任何帮助或指示!

3 个答案:

答案 0 :(得分:5)

你不能,至少不能直接。从资源(.resx)文件生成的强类型类暴露静态,而不是实例方法。

因此,他们无法实现接口方法,也不是虚拟的; Moq要求至少满足其中一个条件才能创建模拟。

要解决这个问题,你可以创建一个抽象,就像其他任何东西一样:

public interface IResources
{
    string MyStringResource { get; }
}

您将此实现传递(或注入)到您的控制器中,然后将其传递给您的Index方法。该实现可能如下所示:

public class ResourcesWrapper : IResources
{
    public string MyStringResource 
    { 
        get 
        { 
            return Resources.Strings.MyStringResource; 
        } 
    }
}

然后,当您进行测试时,您可以使用Moq创建IResources接口的模拟,并将其传递给您的控制器,如下所示:

// Create the mock.
var mock = new Mock<IResources>();

// Setup the property.
mock.SetupProperty(m => m.MyStringResource, "My Mocked Value");

// Pass the object somewhere for use.
Assert.AreEqual(mock.Object.MyStringResource, "My Mocked Value");

答案 1 :(得分:2)

因此,在实施casperOne的答案后,我遇到了另一个错误:

我收到IOException陈述:

"Could not load file or assembly 'App_GlobalResources' or one of its dependencies. The system cannot find the file specified.":"App_GlobalResources"

Scott Allen 为此问题提供了reason and inherent solution

所以我所做的是在我的web项目中名为'TResources'的新文件夹中创建了一个新资源文件,名为'TResources'纯粹因为它是一个仅用于测试目的的Resources文件夹(聪明,是吗?)

然后,我将ResourcesWrapper类的属性更改为TResources.Strings.MyStringResource而不是Resources.Strings.MyStringResource

注意: IResources界面中的属性不能是只读,就像设置模拟对象时一样,如果属性为只读它将失败,因为无法设置该值。

因此,IResources应该看起来像这样:

public interface IResources
{
    string MyStringResource { get; set; }
}
然后

ResourcesWrapper应该像这样实施IResources

public class ResourcesWrapper : IResources
{
    public string MyStringResource 
    { 
        get 
        { 
            return TResources.Strings.MyStringResource; 
        } 
        set
        {
            //do nothing
        }
    }
}

这样你就可以在单元测试中实现成功的模拟,如下所示:

var mock = new Mock<IResources>();
mock.SetupProperty(m => m.MyStringResource, "");

注意:您不必在上述方法的initialValue参数中指定任何内容,因为该属性将返回从Strings.resx检索到的值。

我的问题到此结束,我希望这对互联网上的其他人有所帮助!

答案 2 :(得分:0)

This responsesimilar Stack Overflow question Darin Dimitrov提供了一种更简单的方法。这都是关于修改Resources.resx文件属性以支持单元测试。