Unit-Testing local and global resources in asp.net mvc
-
06-07-2019 - |
Question
I have a class that wraps the GetGlobalResourceObject and GetLocalResourceObjet so they can be used easily in MVC. The model validation classes then load the error messages dynamically from resource files. The problem is unit testing. The code uses "~/", and while everything functions correctly when the solution is run, I cannot see how to make the unit tests because I always receive the following error "System.Web.HttpException: The application relative virtual path '~/' cannot be made absolute, because the path to the application is not known."
The code that throws the exception is the following, used to evaluate an expression and return a global resource object.
Private Function GetExpressionFields(ByVal expression As String) As ResourceExpressionFields
Return GetExpressionFields(expression, "~/")
End Function
Private Function GetExpressionFields(ByVal expression As String, ByVal path As String) As ResourceExpressionFields
Dim context As New ExpressionBuilderContext(path)
Dim resource_builder As New ResourceExpressionBuilder()
Dim fields As ResourceExpressionFields
fields = DirectCast(resource_builder.ParseExpression(expression, GetType(String), context), ResourceExpressionFields)
Return fields
End Function
Any ideas on how to test this and other code that uses resource files?
Solution
I took a slightly different approach. I use resource files outside of the App_* directories, in which case the IDE will add a custom tool to the file to generate a strongly typed wrapper for the resources that works anywhere in the solution, including in views, and behaves during unit tests: http://odetocode.com/Blogs/scott/archive/2009/07/15/13211.aspx
That's not an exact answer to your question, but I believe getting the App_* resources to behave correctly under all conditions was quite a bit of work.
OTHER TIPS
You could create a property in your ResourceExtensions class, for example bool IsInTestScope, and then in your test class set it on true, and inside method which returns localized text do something like this:
public static string Resource(this Controller controller, string expression, params object[] args)
{
if (!IsInTestScope)
{
ResourceExpressionFields fields = GetResourceFields(expression, "~/");
return GetGlobalResource(fields, args);
}
return string.Empty;
}
I've found approach for testing code that uses resources inside App_* directories. I described my solution in my blog link text