如何使用 Moq 和 xUnit 测试异步方法

How to test async methods with Moq and xUnit

我有以下调用插入和更新方法的方法。

条件

  1. 在下面的 ProcessBspLoan 函数中,我调用了另一个名为 getBspData 的函数 如果 getBspData returns 任何结果。我将插入结果 并且 更新 数据库作为特定 Id

    的成功
  2. 如果 getBspData 抛出任何异常我只会 更新 数据库作为特定 ID 的失败而不 插入

这是给定的 class

中的 ProcessBspLoan 函数
    public class BspLoanProcessor : IBspLoanProcessor
    {
        private readonly IBspClient _bspService;
        private readonly IBspRepository _bspRepository;
        private readonly ILogger<BspLoanProcessor> _logger;
        private readonly IMapper _mapper;
        private readonly IFhaRepository _fhaRepository;

        public BspLoanProcessor(IBspClient bspService, ILogger<BspLoanProcessor> logger, 
            IMapper mapper, IBspRepository bSPRepository, IFhaRepository fhaRepository)
        {
            _bspService = bspService;
            _logger = logger;
            _mapper = mapper;
            _bspRepository = bSPRepository;
            _fhaRepository = fhaRepository;
        }

        public async Task<bool> ProcessBspLoan(BspLoanDetails bspLoanDetails, string transactionId, string triggerType)
        {
            FhaTransactionDetails fhaData = _mapper.Map<FhaTransactionDetails>(bspLoanDetails);

            try
            {
                ////////////////////////////Calling getBspData///////////////////////////////////////
                var result = await _bspService.getBspData(bspLoanDetails.NsmLoanNumber, transactionId);

                result.TransactionId = transactionId;

                await _bspRepository.InsertBspResponse(result);
                
                await _fhaRepository.UpdateFhaTransactionWithLoanNumber(transactionId,"SUCCESS");
                return true;
            }
            catch(Exception ex)
            {
                await _fhaRepository.UpdateFhaTransactionWithLoanNumber(transactionId,"FAIL");
                return false;
            }
        }
    }

我为上述函数编写了测试方法,想根据提供的输入检查它是返回真还是假

这是我的测试函数

    public async Task Test1Async()
    {
        Mock<IBspLoanProcessor> _bspLoanProcessor = new Mock<IBspLoanProcessor>();
        Mock<IBspRepository> _bspRepository = new Mock<IBspRepository>();
        Mock<IFhaRepository> _fhaRepository = new Mock<IFhaRepository>();
        Mock<IBspClient> _bspClient = new Mock<IBspClient>();
        BspLoanDetails bspLoanDetails = new BspLoanDetails
        {
            TriggerType = "BLOB",
            Attempts = 1,
            FirstRunDateTime = DateTime.Now.ToUniversalTime()
        };
        ----> 1
        _bspClient.Setup(x => x.getBspData(It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(new BspResponseDetails()));
        ----> 2
        _bspRepository.Setup(x => x.InsertBspResponse(It.IsAny<BspResponseDetails>())).Returns(Task.CompletedTask);
        ----> 3
        _fhaRepository.Setup(x => x.UpdateFhaTransactionWithLoanNumber(It.IsAny<string>(),It.IsAny<string>())).Returns(Task.CompletedTask);
        bool value = await _bspLoanProcessor.Object.ProcessBspLoan(bspLoanDetails, "123", "SCHEDULE");
        Assert.True(value);
    }

在上面的测试中,我检查的是第一个条件

  1. 每当有人调用获取数据时,我都会将数据作为对象返回
  2. 插入BspResponsemethod我也回来了task.completedTask
  3. UpdateFhaTransactionWithLoanNumber我也回来了task.completedTask

实际预期输出为 true,但返回 false。

我是 Moq 和 xUnit 的新手。请帮助我解决这个问题并测试异步和等待方法。

IBspClient 接口

    public interface IBspClient
    {
        Task<BspResponseDetails> getBspData(string loanNumber,string tid);

        Task<BspHealthCheck> GetHealthStatus();
    }

IBspRepository 接口

    public interface IBspRepository
    {
        Task InsertBspResponse(BspResponseDetails bsp);
    }

IFhaRepository 接口

    public interface IFhaRepository
    {
        Task UpdateFhaTransactionWithLoanNumber(string tid, string status);    
    }

提前致谢

bool value = await _bspLoanProcessor.Object

您正在对模拟调用一个方法。你不应该模拟被测系统,你只模拟它的依赖关系。

只需 new 您想要测试的 class,否则您将测试您的模拟框架是否按照您的设置执行。

并且由于您没有设置 ProcessBspLoan(),它 return 是其 return 值的默认值,因此 false