2017-04-15 115 views
22

與ILogger單元測試這是我的控制器:如何在ASP.NET核心

public class BlogController : Controller 
{ 
    private IDAO<Blog> _blogDAO; 
    private readonly ILogger<BlogController> _logger; 

    public BlogController(ILogger<BlogController> logger, IDAO<Blog> blogDAO) 
    { 
     this._blogDAO = blogDAO; 
     this._logger = logger; 
    } 
    public IActionResult Index() 
    { 
     var blogs = this._blogDAO.GetMany(); 
     this._logger.LogInformation("Index page say hello", new object[0]); 
     return View(blogs); 
    } 
} 

正如你可以看到我有2只依賴,一個IDAO和​​

這是我的測試類,我使用xUnit來測試和Moq創建模擬和存根,我可以嘲笑DAO容易,但與​​我不知道該怎麼做,所以我只是傳遞null和註釋掉調用登錄控制器時運行測試。有沒有辦法測試,但仍然保持記錄器?

public class BlogControllerTest 
{ 
    [Fact] 
    public void Index_ReturnAViewResult_WithAListOfBlog() 
    { 
     var mockRepo = new Mock<IDAO<Blog>>(); 
     mockRepo.Setup(repo => repo.GetMany(null)).Returns(GetListBlog()); 
     var controller = new BlogController(null,mockRepo.Object); 

     var result = controller.Index(); 

     var viewResult = Assert.IsType<ViewResult>(result); 
     var model = Assert.IsAssignableFrom<IEnumerable<Blog>>(viewResult.ViewData.Model); 
     Assert.Equal(2, model.Count()); 
    } 
} 

回答

26

只是嘲笑它,以及其他任何依賴性:

var mock = new Mock<ILogger<BlogController>>(); 
ILogger<BlogController> logger = mock.Object; 

//or use this short equivalent 
logger = Mock.Of<ILogger<BlogController>>() 

var controller = new BlogController(logger); 

你可能需要安裝Microsoft.Extensions.Logging.Abstractions包使用ILogger<T>

而且你可以創建一個真實的記錄:

var serviceProvider = new ServiceCollection() 
    .AddLogging() 
    .BuildServiceProvider(); 

var factory = serviceProvider.GetService<ILoggerFactory>(); 

var logger = factory.CreateLogger<BlogController>(); 
+1

登錄到調試輸出窗口調用AddDebug()的工廠:工廠變種= serviceProvider.GetService ()AddDebug(); – spottedmahn

4

您可以使用一個模擬爲存根,如伊利亞建議,如果你沒有真正試圖測試記錄方法本身被調用。如果是這種情況,嘲笑記錄器不起作用,你可以嘗試幾種不同的方法。

我寫了一個short article顯示了各種方法。該文章包括a full GitHub repo with each of the different options。最後,我的建議是使用自己的適配器,而不是直接使用ILogger類型,如果你需要能夠測試它被調用。

https://ardalis.com/testing-logging-in-aspnet-core

6

其實,我發現Microsoft.Extensions.Logging.Abstractions.NullLogger <>它看起來像一個完美的解決方案。

+0

這似乎只適用於.NET Core 2.0,而不適用於.NET Core 1.1。 –

2

使用使用ITestOutputHelper(來自xunit)捕獲輸出和日誌的自定義記錄器。以下是僅將state寫入輸出的小樣本。

public class XunitLogger<T> : ILogger<T>, IDisposable 
{ 
    private ITestOutputHelper _output; 

    public XunitLogger(ITestOutputHelper output) 
    { 
     _output = output; 
    } 
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) 
    { 
     _output.WriteLine(state.ToString()); 
    } 

    public bool IsEnabled(LogLevel logLevel) 
    { 
     return true; 
    } 

    public IDisposable BeginScope<TState>(TState state) 
    { 
     return this; 
    } 

    public void Dispose() 
    { 
    } 
} 

用它在你的單元測試一樣

public class BlogControllerTest 
{ 
    private XunitLogger<BlogController> _logger; 

    public BlogControllerTest(ITestOutputHelper output){ 
    _logger = new XunitLogger<BlogController>(output); 
    } 

    [Fact] 
    public void Index_ReturnAViewResult_WithAListOfBlog() 
    { 
    var mockRepo = new Mock<IDAO<Blog>>(); 
    mockRepo.Setup(repo => repo.GetMany(null)).Returns(GetListBlog()); 
    var controller = new BlogController(_logger,mockRepo.Object); 
    // rest 
    } 
}