模拟接口返回 NULL

Mocked Interface returning NULL

我读过类似的问题,但无法解决我自己的问题。我正在使用 xUnit,当我的一个方法调用时,我 运行 遇到了一个问题,它返回 null 但实际上我已经嘲笑了它。

界面

public interface IApplicantService
{
    Task<Applicant> AddAsync(Applicant applicant);
    // other methods
}

测试用例

public class ApplicationControllerTests
{
    private readonly Mock<IApplicantService> _mockApplicantService;
    private readonly ApplicantController _applicantController;
    private readonly IMapper _mockMapper;

    public ApplicationControllerTests()
    {
        _mockApplicantService = new Mock<IApplicantService>();

        var mapperConfig = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(new ResourceToModelProfile());
            cfg.AddProfile(new ModelToResourceProfile());
        });
        _mockMapper = mapperConfig.CreateMapper();

        _applicantController = new ApplicantController(_mockApplicantService.Object, _mockMapper);
    }

    [Fact]
    public async void CreateAsync_WhenApplicantNotExist_ShouldReturn_CreatedAtActionResult_With_Resource()
    {
        var applicantDto = new ApplicantCreateDto
        {
            PersonId = 1,
            VacancyId = 1
        };

        _mockApplicantService.Setup(e => e.AddAsync(It.IsAny<Applicant>()))
                            .Returns(Task.FromResult(new Applicant { Id = 1, PersonId = 1, VacancyId = 1}));

        var result = await _applicantController.CreateAsync(applicantDto);

        var createdAtActionResult = result as CreatedAtActionResult;

        var model = createdAtActionResult.Value as ApplicantResponseDto;

        var actual = model.PersonId;

        Assert.NotNull(model);            
        Assert.Equal(1, actual);
        Assert.NotNull(createdAtActionResult);
    }
}

控制器

[HttpPost]
[Route("CreateAsync")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateAsync([FromBody] ApplicantCreateDto applicantCreateDto)
{
    try
    {
        var applicant = _mapper.Map<ApplicantCreateDto, Applicant>(applicantCreateDto);

        var result = await _applicantService.AddAsync(applicant);
        // here, result is null, but it was mocked to return an Applicant object

        var resource = _mapper.Map<Applicant, ApplicantResponseDto>(result);

        return CreatedAtAction(nameof(GetAsync), new { id = result.Id }, resource);
    }
    catch (ResourceExistException ex)
    {
        return Conflict(ex.Message);
    }
    catch(Exception ex)
    {   
        // log exception             
        return StatusCode(500);
    }
}

模拟方法返回 null,我得到 System.NullReferenceException

这就是你的固定单元测试的样子:

[Fact]
public async Task CreateAsync_WhenApplicantNotExist_ShouldReturn_CreatedAtActionResult_With_Resource()
{
    //Arrange
    var applicantDto = new ApplicantCreateDto { PersonId = 1, VacancyId = 1 };
    var applicant = new Applicant { Id = 1, PersonId = 1, VacancyId = 1 };

    _mockApplicantService
        .Setup(svc => svc.AddAsync(It.IsAny<Applicant>()))
        .ReturnsAsync(applicant);

    //Act
    var result = await _applicantController.CreateAsync(applicantDto);

    //Assert
    var createdAtActionResult = Assert.IsAssignableFrom<CreatedAtActionResult>(result);
    var model = Assert.IsAssignableFrom<ApplicationResponseDto>(createdAtActionResult.Value);
    Assert.Equal(1, model.PersonId);
}
  • 我已将 async void 替换为 async Task 这样您的 await 将得到正确评估
  • 我已将 Returns(Task.FromResult(...)) 更改为 ReturnsAsync(...) 因为这是 specify return value in case of async methods
  • 的推荐方式
  • 我还添加了一些注释以将单元测试的不同阶段彼此分开 (Arrange-Act-Assert)
  • 我已将您的断言逻辑更改为使用 IsAssingableFrom 来验证类型本身而不是进行空值检查