尝试使用 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);
我正在尝试为我的服务编写一些单元测试。
我只是想掌握一个简单的窍门,只是测试我的服务的 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);