xunit 和模拟返回 null 而不是字符串

问题描述 投票:0回答:2

我遇到了 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);  
    }
    }
  }
.net moq xunit
2个回答
0
投票

测试将测试替身配置为期望被测系统 (SUT) 接收到的值之外的其他值:

_canOpenPort.Setup(c => c.ValidateWearerAsync("borrow", "643674")).Returns(task);

[...]

var response = await controller.AccessControl("BorrowCabinet", "368629398762");

确保这两对相同。如果这些值与

Setup
不匹配,Moq 将返回默认值,这通常意味着空引用。

您可能还想使用

ReturnsAsync
而不是
Returns
来简化测试代码。


0
投票

最小起订量将与设置使用的值相匹配。由于

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");
© www.soinside.com 2019 - 2024. All rights reserved.