我正在为 MVC3 Web 项目中的控制器编写单元测试,但是当我的测试尝试访问这样的资源时会抛出异常:
return Index(Resources.Strings.MyStringResource);
该资源是一个.resx
名为Strings
.
我正在使用Moq库来实现HttpContextBase
功能的单元测试,所以我想知道如何使用 Moq 库来访问 App_GlobalResource。
任何帮助或指示将不胜感激!
我正在为 MVC3 Web 项目中的控制器编写单元测试,但是当我的测试尝试访问这样的资源时会抛出异常:
return Index(Resources.Strings.MyStringResource);
该资源是一个.resx
名为Strings
.
我正在使用Moq库来实现HttpContextBase
功能的单元测试,所以我想知道如何使用 Moq 库来访问 App_GlobalResource。
任何帮助或指示将不胜感激!
你不能,至少不能直接。从资源 (.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");
因此,在实施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提供了这个问题的原因和内在解决方案。
所以我所做的是在我的 web 项目中名为“TResources”的新文件夹中创建了一个新资源文件,命名为“TResources”纯粹是因为它是一个仅用于测试目的的资源文件夹(聪明,嗯?)
然后我将ResourcesWrapper
类的属性更改为 returnTResources.Strings.MyStringResource
而不是Resources.Strings.MyStringResource
.
注意:IResources
接口中的属性不能是只读的,如设置mock对象时,如果属性是只读的,会因为无法设置值而失败。
因此,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
.
我的问题到此结束,我希望这对互联网领域的其他人有所帮助!
Darin Dimitrov对类似Stack Overflow 问题的回答提供了一种更简单的方法。这完全是关于修改 Resources.resx 文件属性以支持单元测试。