尝试使用 xUnit 测试服务时,构造函数参数没有匹配的夹具数据。这是什么意思,我的问题在哪里?

Constructor parameters did not have matching fixture data, when trying to test a service using xUnit. What does this mean and where is my issue?

我正在尝试为我的服务编写一些单元测试。

我只是想掌握一个简单的窍门,只是测试我的服务的 GetAsync 方法,使用 xUnit 和 Moq。

这是我的代码:

namespace HRB_Server.Tests.Services
{
    public class PhaseServiceTest
    {
        private readonly Mock<IRepository<Phase>> _repository;
        private readonly Mock<IMapper> _mapper;
        private readonly Mock<HrbContext> _context;

        public PhaseServiceTest()
        {
            _repository = new Mock<IRepository<Phase>>();
            _mapper = new Mock<IMapper>();
            _context = new Mock<HrbContext>();
        }

        [Fact]
        public void GetPhase_ActivePhaseObject_PhaseShouldExist()
        {
            // Arrange
            var newGuid = Guid.NewGuid();
            var phase = GetSamplePhase(newGuid);

            _repository.Setup(x => x.GetAsync(It.IsAny<Guid>()))
                .Returns(GetSamplePhase(newGuid));

            var phaseService = new PhaseService(_repository.Object, _mapper.Object, _context.Object);

            // Act
            var result = phaseService.GetAsync(newGuid);

            // Assert (expected, actual)
            Assert.Equal(phase.Id, result.Id);
    }
}

此代码产生以下错误:

The following constructor parameters did not have matching fixture data: IMapper mapper, HrbContext context

我的“真实”服务需要 3 个对象,IRepository、自动映射器和上下文。

我做错了什么?

编辑:

这是我的 IRepository class:

public interface IRepository<T> : IDisposable
{
    Task<T> GetAsync(Expression<Func<T, bool>> predicate);
    Task<T> GetAsync(Guid id);
} 

这是我的上下文 class:

public class HrbContext : IdentityDbContext<ApplicationUser>
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    // DBsets are here...

     public HrbContext(DbContextOptions<HrbContext> options, IHttpContextAccessor httpContextAccessor)
        : base(options)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
         ... 
    }
}

Mapper class 实际上是来自 Nuget 包的“AutoMapper”。

你的错误是因为你的 HrbContext 有一个带有 2 个参数的构造函数,你在模拟时没有指定。

public HrbContext(DbContextOptions<HrbContext> options, IHttpContextAccessor httpContextAccessor) : base(options)
{
    _httpContextAccessor = httpContextAccessor;
}

Moq 在模拟时需要一个 public 默认构造函数,或者您需要使用构造函数参数创建模拟对象。

由于您已经在模拟 _repository.GetAsync 的 return 值,因此您实际上不需要 DbContext 中的任何实际实现,因为它甚至不会被调用。

在这种情况下,由于我们不想模拟或不需要 DbContextOptions<HrbContext>IHttpContextAccessor 的真正实现,因此将它们作为 null 传递。

_context = new Mock<HrbContext>(null, null);

如果您确实需要它们(在其他测试中等),也可以模拟它们或通过真实实例传递:

var options = new DbContextOptions<HrbContext>(...);
var httpContextAccessor = new HttpContextAccessor(...);
_context = new Mock<HrbContext>(options, httpContextAccessor);