2016-11-18 23 views
7

Tôi đang viết một trường hợp thử nghiệm đơn giản để kiểm tra bộ điều khiển của tôi gọi bộ nhớ cache trước khi gọi dịch vụ của tôi. Tôi đang sử dụng xUnit và Moq cho nhiệm vụ.Cách thích hợp để kiểm tra ASP.NET Core IMemoryCache

Tôi đang gặp sự cố vì GetOrCreateAsync<T> là một phương pháp tiện ích mở rộng và không thể mô phỏng khuôn khổ đó bằng khung. Tôi dựa vào chi tiết nội bộ để tìm ra tôi có thể thử TryGetValue thay vào đó và nhận được ngay với thử nghiệm của tôi (xem https://github.com/aspnet/Caching/blob/c432e5827e4505c05ac7ad8ef1e3bc6bf784520b/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs#L116)

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

tôi không thể ngủ với thực tế là tôi đang nhìn trộm vào các chi tiết thực hiện MemoryCache và nó có thể thay đổi bất cứ lúc nào.

Để tham khảo, đây là mã SUT:

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

có bạn khuyên bạn nên kiểm tra bất kỳ khác nhau?

+2

Bạn không nên kiểm tra 'IMemoryCache' vì nó là một phần của thư viện. Các tác giả của thư viện nên làm bài kiểm tra. –

Trả lời

14

Thành thật mà nói, tôi khuyên bạn không nên thử nghiệm tương tác này.

Tôi sẽ tiếp cận trường hợp thử nghiệm này một chút khác nhau: điều bạn thực sự quan tâm là khi bộ điều khiển của bạn truy lục dữ liệu từ ISearchService nó không yêu cầu lại dữ liệu và sẽ trả về kết quả từ cuộc gọi trước đó.

Thực tế là một IMemoryCache được sử dụng phía sau hậu trường chỉ là chi tiết triển khai. Tôi thậm chí sẽ không bận tâm thiết lập một kiểm tra đôi cho nó, tôi sẽ chỉ sử dụng một thể hiện của đối tượng Microsoft.Extensions.Caching.Memory.MemoryCache.

thử nghiệm mới của tôi sẽ giống như thế này:

[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

Tôi thích cách tiếp cận của bạn nhiều hơn. Cảm ơn! –

Các vấn đề liên quan