2016-12-21 3 views
1

私は、次の拡張メソッドを持つ静的クラスを持っているとしましょう。キャッシュからファイルを取得するか、ディスクから読み込み、キャッシュに入れません。コンテンツに何らかの変更を加えます。属性):私は、メソッドからのすべての依存関係を削除する必要がこのコードをテスト可能にするためにかみそりのビューで使用されるテストスタティックメソッドをどのようにユニット化しますか?

@Html.DoSomething("/path/to/file", new List<string>(){"param1", "param2"}); 

public static class Foo 
{ 
    public static DoSomething(this HtmlHelper helper, string url, List<string> parameters) 
    { 
    string content = String.Empty; 
    var cache = HttpContext.Current.Cache[url]; 

    if (cache == null) 
    { 
     string absolute_path = WebPages.HelperPage.Server.MapPath(url); 
     content = File.ReadAllText(absolute_path); 
     HttpContext.Current.Cache.Add(url, content, ...); 
    } 
    else 
    { 
     content = cache.ToString(); 
    } 

    //make a few changes to content (e.g., add some tags or attributes) 
    content = makeChangesToContent(content, parameters); 

    return MvcHtmlString.Create(content); 
    } 
} 

このメソッドは、このようにかみそりビューで使用されています。しかし、それは静的で、かみそりのビューで使用されるので、私はそれを正しく行う方法がわかりません。

唯一の選択肢は、いくつかの偽の方法で外部依存関係を偽造するためにShimsを使用することです。しかし、単体テスト・コードは少し重く見え、それを実行するには約200msかかります。ここで

は、ユニットテストの簡単な例です:

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

は、それはそれをテストするための正しい方法は何ですか?より良い選択肢はありますか? あなたの経験から、このような静的メソッドをテストする最良の方法は何ですか?

+0

これは役に立ちます - http://stackoverflow.com/questions/4379450/mock-httpcontext-current-in-test-init-method – Carra

+0

使用しているVisual Studioのエディションは何ですか? – zaitsman

答えて

0

あなたの方法はあまり、私はそれを分割したいん:

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(){} 
} 

をあなたはその後、filereadingをモックとディスクから読み込むことなく、あなたのDO変更をテストすることができます。

1

HtmlHelpersは、ビュー用にHTMLを出力するためのものです。ここで

は、コントローラのアクションにする必要がありますようにあなたが書いたヘルパーが本当に見えます良い説明Why do we use HTML helper in ASP.NET MVC?

です。

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

IProviderFilePath前線Server.MapPathのコールとIProvideCacheSupport前線キャッシュへの呼び出しをラップするクラスをラップしたクラスのようなもの。あなたは両方を嘲笑することができます。

関連する問題