NSubstitute 创建替换实例的两个实例
NSubstitute creating two instances of substituted instance
我有一个基本的 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()
方法的单个调用(在基础 class 构造函数上调用),但是在 controller.SomeAction() 方法的上下文中查看调试时,相同的 _receivedCalls
属性 按预期显示了对 logger.Information()
的两次调用,但没有显示对 ForContext()
.
的调用
所以在我看来,出于某种原因,Nsubstitute 正在创建替代 class 的两个单独实例,一个在基本控制器的上下文中,一个在实际控制器中 - 为什么会这样以及如何我避开了?
您需要像这样存根 ForContext
return:
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>());
或:
logger.ReceivedWithAnyArgs().Information("");
我有一个基本的 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()
方法的单个调用(在基础 class 构造函数上调用),但是在 controller.SomeAction() 方法的上下文中查看调试时,相同的 _receivedCalls
属性 按预期显示了对 logger.Information()
的两次调用,但没有显示对 ForContext()
.
所以在我看来,出于某种原因,Nsubstitute 正在创建替代 class 的两个单独实例,一个在基本控制器的上下文中,一个在实际控制器中 - 为什么会这样以及如何我避开了?
您需要像这样存根 ForContext
return:
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>());
或:
logger.ReceivedWithAnyArgs().Information("");