我遇到了 xUnit.net 和 Moq 测试问题,我已经模拟了我的控制器的依赖项,并将模拟设置为返回
Task<string>
,但我的 response.Value
在这里为空。有人可以帮忙解决这个问题吗?
namespace TestProject
{
public class CabinetControllerTest : ControllerBase
{
private Mock<IWearerPort> _canOpenPort;
private Mock<ITwoTraceLogger> _twoTraceLogger;
private Mock<ITransactionPort> _transaction;
public CabinetControllerTest()
{
_canOpenPort = new Mock<IWearerPort>();
_transaction = new Mock<ITransactionPort>();
_twoTraceLogger = new Mock<ITwoTraceLogger>();
}
[Fact]
public async void AccessControl_Success_Test()
{
//Arrange
Task<string> task = Task.FromResult<string>("Forbidden");
_canOpenPort.Setup(c => c.ValidateWearerAsync("borrow",
"643674")).Returns(task);
var controller = new CabinetController(_transaction.Object,
_canOpenPort.Object, _twoTraceLogger.Object);
var expected = Ok("Forbidden");
//Act
var response = await controller.AccessControl("BorrowCabinet",
"368629398762");
var actual = Ok(response.Value);
//Assert
Assert.Equal(expected, actual);
}
}
namespace MsCabinetGateway.Adapters.RestApiAdapter.Controllers
{
[ApiController]
[Route("[controller]")]
public class CabinetController : ControllerBase
{
private readonly IWearerPort _canOpenPort;
private readonly ITwoTraceLogger _twoTraceLogger;
private readonly ITransactionPort _transaction;
public CabinetController(ITransactionPort transaction,
IWearerPort canOpen, ITwoTraceLogger twoTraceLogger)
{
_twoTraceLogger = twoTraceLogger;
_canOpenPort = canOpen;
_transaction = transaction;
}
[HttpGet]
[Route("[controller]/accesscontrol")]
public async Task<ActionResult<string>> AccessControl(string
clientID, string cardId)
{
_twoTraceLogger.LogTrace("CabinetController gets called");
var result = await
_canOpenPort.ValidateWearerAsync(clientID,cardId);
return Ok(result);
}
[HttpPost]
[Route("[controller]/addtransactions")]
public async Task<ActionResult<ulong>>
AddTransactions(List<CabinetTransactionEvent>
cabinetTransactionEvents)
{
return await
_transaction.CheckTransaction(cabinetTransactionEvents);
}
}
}
测试将测试替身配置为期望被测系统 (SUT) 接收到的值之外的其他值:
_canOpenPort.Setup(c => c.ValidateWearerAsync("borrow", "643674")).Returns(task);
[...]
var response = await controller.AccessControl("BorrowCabinet", "368629398762");
确保这两对相同。如果这些值与
Setup
不匹配,Moq 将返回默认值,这通常意味着空引用。
您可能还想使用
ReturnsAsync
而不是 Returns
来简化测试代码。
最小起订量将与设置使用的值相匹配。由于
CabinetController.AccessControl
只是直接将 clientID
和 cardId
传递到 ValidateWearerAsync
,因此您需要将设置中的值与传递给控制器的值相匹配。例如:
_canOpenPort.Setup(c => c.ValidateWearerAsync("BorrowCabinet",
"368629398762")).Returns(task);
var response = await controller.AccessControl("BorrowCabinet", "368629398762");
It.IsAny
:
_canOpenPort.Setup(c => c.ValidateWearerAsync(It.IsAny<string>(), It.IsAny<string>()))
.Returns(task);
但总的来说我建议避免它。
附注
Returns(task)
更改为 ReturnsAsync
,值为:
_canOpenPort.Setup(c => c.ValidateWearerAsync(...))
.ReturnsAsync("Forbidden");