2016-11-18 15 views
7

私のサービスを呼び出す前に、コントローラがキャッシュを呼び出すかどうかをテストする簡単なテストケースを作成しています。私はタスクにxUnitとMoqを使用しています。ASP.NETコアの適切なテスト方法IMemoryCache

GetOrCreateAsync<T>が拡張メソッドであり、フレームワークでモックできないため、私は問題に直面しています。私は

[Theory, AutoDataMoq] 
public async Task GivenPopulatedCacheDoesntCallService(
    Mock<IMemoryCache> cache, 
    SearchRequestViewModel input, 
    MyViewModel expected) 
{ 
    object expectedOut = expected; 
    cache 
     .Setup(s => s.TryGetValue(input.Serialized(), out expectedOut)) 
     .Returns(true); 
    var sut = new MyController(cache.Object, Mock.Of<ISearchService>()); 
    var actual = await sut.Search(input); 
    Assert.Same(expected, actual); 
} 

は私がMemoryCacheの実装の詳細と、それに覗き見していたという事実に眠ることができない(https://github.com/aspnet/Caching/blob/c432e5827e4505c05ac7ad8ef1e3bc6bf784520b/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs#L116を参照)の代わりにTryGetValueを嘲笑し、私のテストで逃げることができますを把握するために、内部の詳細に依存していましたいつでも変更することができます。参考のため

、これはSUTコードです:

public async Task<MyViewModel> Search(SearchRequestViewModel request) 
{ 
    return await cache.GetOrCreateAsync(request.Serialized(), (e) => search.FindAsync(request)); 
} 

あなたは違った任意のテスト勧めますか?

+2

私の新しいテストは、次のようになります。図書館の著者は、テストを行うべきです。 –

答えて

14

私はこの相互作用を全くテストしないことをお勧めします。

私はこのテストケースに少し違ったアプローチをします:実際に心配しているのは、コントローラがデータを再び取得して前の呼び出しから結果を返すべきでないということです。

IMemoryCacheがバックグラウンドで使用されているという事実は実装の詳細です。私はそれのためのテストのダブルを設定する気にしないだろう、私はちょうどMicrosoft.Extensions.Caching.Memory.MemoryCacheオブジェクトのインスタンスを使用します。それはライブラリの一部であるので、あなたは `IMemoryCache`をテストするべきではありません

[Theory] 
public async Task GivenResultAlreadyRetrieved_ShouldNotCallServiceAgain() 
{ 
    // Arrange 
    var expected = new MyViewModel(); 
    object actualOut; 

    var cache = new MemoryCache(new MemoryCacheOptions()); 
    var searchService = new Mock<ISearchService>(); 

    var input = new SearchRequestViewModel(); 

    searchService 
     .SetupSequence(s => s.FindAsync(It.IsAny<SearchRequestViewModel>())) 
     .Returns(Task.FromResult(expected)) 
     .Returns(Task.FromResult(new MyViewModel())); 

    var sut = new MyController(cache, searchService.Object); 

    // Act 
    var resultFromFirstCall = await sut.Search(input); 
    var resultFromSecondCall = await sut.Search(input); 

    // Assert 
    Assert.Same(expected, resultFromFirstCall); 
    Assert.Same(expected, resultFromSecondCall); 
} 
+0

私はあなたのアプローチがもっと好きです。ありがとう! –

関連する問題