我有一个基础ApiController供我的控制器继承:
public BaseApiController(ILogger logger) : ApiController
{
private readonly ILogger _logger;
public BaseApiController(ILogger logger)
{
_logger = logger.ForContext("SomeContext");
}
}
一个简单的控制器,它继承自基础控制器:
public SomeController : BaseApiController
{
public SomeController(ILogger logger) : base(logger)
{ }
public IHttpActionResult SomeAction()
{
_logger.Information("Start doing something...");
//Do stuff...
_logger.Information("End doing something...");
return Ok();
}
}
我使用Xunit和Nsubstitute为控制器创建了一个简单的测试:
public void SomeAction_ReturnsOk()
{
//Arrange
var logger = Substitute.For<ILogger>();
var controller = new SomeController(logger) {
Request = Substitute.For<HttpRequestMessage>()
};
//Act
var result = controller.SomeAction();
//Assert
logger.ReceivedWithAnyArgs().Information(Arg.Any<string>());
}
执行测试用例时,它无法声明它已收到对logger.Information()方法的零调用。在调试_receivedCalls属性(在替换的ILogger上)时,如果调试上下文在测试用例本身内,则显示对logger.ForContext()
方法的单个调用(称为在基类构造函数上),但是当在controller.SomeAction()方法的上下文中查看调试时,相同的_receivedCalls
属性显示对logger.Information()
的两次调用。预期但不是ForContext()
的号召。
所以在我看来,由于某些原因,Nsubstitute正在创建替代类的两个独立实例,一个在基本控制器的上下文中,另一个在实际控制器中 - 为什么这样,我该如何避免呢?
答案 0 :(得分:2)
你需要像这样存档ForContext
:
public void SomeAction_ReturnsOk()
{
//Arrange
var logger = Substitute.For<ILogger>();
logger.ForContext(Arg.Any<string>()).Returns(logger);
var controller = new SomeController(logger) {
Request = Substitute.For<HttpRequestMessage>()
};
//Act
var result = controller.SomeAction();
//Assert
logger.Received().Information(Arg.Any<string>());
}
我将断言更改为:
logger.Received().Information(Arg.Any<string>());
OR:
logger.ReceivedWithAnyArgs().Information("");