C# 如何对razor视图中使用的静态方法进行单元测试?
假设我有一个具有以下扩展方法的静态类,它从缓存中检索文件或从磁盘读取文件,如果文件不在缓存中,则将其放入缓存+对内容进行一些更改(例如,添加标记或属性):C# 如何对razor视图中使用的静态方法进行单元测试?,c#,asp.net-mvc,unit-testing,razor,static-methods,C#,Asp.net Mvc,Unit Testing,Razor,Static Methods,假设我有一个具有以下扩展方法的静态类,它从缓存中检索文件或从磁盘读取文件,如果文件不在缓存中,则将其放入缓存+对内容进行一些更改(例如,添加标记或属性): 公共静态类Foo { 公共静态DoSomething(此HtmlHelper帮助程序、字符串url、列表参数) { string content=string.Empty; var cache=HttpContext.Current.cache[url]; if(缓存==null) { 字符串绝对路径=WebPages.HelperPage.
公共静态类Foo
{
公共静态DoSomething(此HtmlHelper帮助程序、字符串url、列表参数)
{
string content=string.Empty;
var cache=HttpContext.Current.cache[url];
if(缓存==null)
{
字符串绝对路径=WebPages.HelperPage.Server.MapPath(url);
content=File.ReadAllText(绝对路径);
HttpContext.Current.Cache.Add(url、内容等);
}
其他的
{
content=cache.ToString();
}
//对内容进行一些更改(例如,添加一些标记或属性)
内容=makeChangesToContent(内容、参数);
返回MvcHtmlString.Create(content);
}
}
此方法在razor视图中使用,如下所示:
@Html.DoSomething("/path/to/file", new List<string>(){"param1", "param2"});
@Html.DoSomething(“/path/to/file”,new List(){“param1”,“param2”});
为了使这段代码可测试,我必须从方法中删除所有依赖项。但是由于它是静态的,并且在razor视图中使用,我不确定如何正确地执行它
我想到的唯一一个选择是使用填隙片用一些假方法来假外部依赖关系。但是单元测试代码看起来有点重,运行它需要大约200毫秒
下面是单元测试的一个快速示例:
[Test]
public void DoSomething_Should_Return_FileContent_From_Cache_When_It_Is_There()
{
string relativeFilePath = "/some/path";
string fileContent = "content";
string cachedKey = String.Empty;
object cachedValue = null;
using (ShimsContext.Create())
{
//Arrange
System.Web.Fakes.ShimHttpContext.CurrentGet = () =>
{
var httpContext = new System.Web.Fakes.ShimHttpContext();
httpContext.CacheGet = () =>
{
var cache = new System.Web.Caching.Fakes.ShimCache();
cache.ItemGetString = (key) =>
{
cachedKey = key;
cachedValue = fileContent;
return fileContent;
};
return cache;
};
return httpContext;
};
//Act
var result = helper.DoSomething(relativeFilePath, new List<string>(){"param1", "param2"});
//Assert
Assert.IsTrue(cachedKey.Equals(relativeFilePath));
Assert.IsTrue(cachedValue.Equals(fileContent));
}
[测试]
public void DoSomething在缓存中时应返回FileContent()
{
字符串relativeFilePath=“/some/path”;
字符串fileContent=“content”;
string cachedKey=string.Empty;
对象cachedValue=null;
使用(ShimsContext.Create())
{
//安排
System.Web.Fakes.ShimHttpContext.CurrentGet=()=>
{
var httpContext=new System.Web.Fakes.ShimHttpContext();
httpContext.CacheGet=()=>
{
var cache=new System.Web.Caching.Fakes.ShimCache();
cache.ItemGetString=(键)=>
{
cachedKey=key;
cachedValue=文件内容;
返回文件内容;
};
返回缓存;
};
返回httpContext;
};
//表演
var result=helper.DoSomething(relativeFilePath,new List(){“param1”,“param2”});
//断言
Assert.IsTrue(cachedKey.Equals(relativeFilePath));
IsTrue(cachedValue.Equals(fileContent));
}
这是正确的测试方法吗?有更好的选择吗?
根据您的经验,测试此类静态方法的最佳方法是什么?您的方法做得太多了,我将其拆分为:
public class GetFileController
{
public string GetFileContent(string url)
{
//Read file from disk & return content
}
public string GetCachedFileContent(string url, Cache cache)
{
if(!cache.ContainsUrl)
cache[url] = GetFileContent(url);
return cache[url];
}
}
public class MakeChangesController()
{
public string DoChanges(){}
}
然后,您可以模拟文件读取并测试您的do更改,而无需从磁盘读取。HTMLHelper应该用于输出视图的Html 这是一个很好的解释 您编写的帮助程序看起来应该在控制器操作中
public class ScratchController : Controller
{
private readonly IProvideFilePath _pathProvider;
private readonly IProvideCacheSupport _cacheProvider;
public ScratchController(IProvideFilePath pathProvider, IProvideCacheSupport cacheProvider)
{
_pathProvider = pathProvider;
_cacheProvider = cacheProvider;
}
[HttpPost]
public FileResult Index(string url, List<string> parameters)
{
var fileContent = _cacheProvider.GetItem(url) as string;
if (string.IsNullOrWhiteSpace(fileContent))
{
var filePath = _pathProvider.MapPath(url);
fileContent = File.ReadAllText(filePath);
_cacheProvider.AddItem(url, fileContent);
}
fileContent = makeChangesToContent(fileContent, parameters);
return Content(fileContent);
}
}
公共类控制器:控制器
{
私有只读IProvideFilePath\u路径提供程序;
私有只读IProvideCacheSupport\u缓存提供程序;
公共ScratchController(IProvideFilePath路径提供程序、IProvideCacheSupport缓存提供程序)
{
_路径提供者=路径提供者;
_cacheProvider=cacheProvider;
}
[HttpPost]
公共文件结果索引(字符串url、列表参数)
{
var fileContent=\u cacheProvider.GetItem(url)作为字符串;
if(string.IsNullOrWhiteSpace(fileContent))
{
var filePath=_pathProvider.MapPath(url);
fileContent=File.ReadAllText(文件路径);
_cacheProvider.AddItem(url、文件内容);
}
fileContent=makeChangesToContent(fileContent,参数);
返回内容(fileContent);
}
}
其中IProviderFilePath前置一个封装Server.MapPath调用的类,IProviderCacheSupport前置一个封装缓存调用的类。这样,您可以模拟两者。这可能会有所帮助-您使用的Visual Studio版本是什么?
public class ScratchController : Controller
{
private readonly IProvideFilePath _pathProvider;
private readonly IProvideCacheSupport _cacheProvider;
public ScratchController(IProvideFilePath pathProvider, IProvideCacheSupport cacheProvider)
{
_pathProvider = pathProvider;
_cacheProvider = cacheProvider;
}
[HttpPost]
public FileResult Index(string url, List<string> parameters)
{
var fileContent = _cacheProvider.GetItem(url) as string;
if (string.IsNullOrWhiteSpace(fileContent))
{
var filePath = _pathProvider.MapPath(url);
fileContent = File.ReadAllText(filePath);
_cacheProvider.AddItem(url, fileContent);
}
fileContent = makeChangesToContent(fileContent, parameters);
return Content(fileContent);
}
}