I'm trying to write some unit tests for my service(s).
I'm just trying to get the hang of a simple one, just testing the GetAsync
method of my service, using xUnit and Moq.
Here's my code:
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);
}
}
This code produces the following error:
The following constructor parameters did not have matching fixture data: IMapper mapper, HrbContext context
My "real" service requires 3 objects, the IRepository, the automapper, and the context.
What am I doing wrong here?
EDIT:
Here's my IRepository class:
public interface IRepository<T> : IDisposable
{
Task<T> GetAsync(Expression<Func<T, bool>> predicate);
Task<T> GetAsync(Guid id);
}
Here's my Context 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)
{
...
}
}
The Mapper class is really the "AutoMapper" one, from the Nuget Package.
CodePudding user response:
Your error is because your HrbContext
has a constructor with 2 parameters, which you haven't specified when mocking.
public HrbContext(DbContextOptions<HrbContext> options, IHttpContextAccessor httpContextAccessor) : base(options)
{
_httpContextAccessor = httpContextAccessor;
}
Moq needs a public default constructor when mocking, or you need to create the mock object with the constructor parameters.
Since you are already mocking the return value of _repository.GetAsync
, you don't really need any real implementation inside the DbContext
as it won't even be called.
In this case, as we don't want to mock or need the real implementation of DbContextOptions<HrbContext>
or IHttpContextAccessor
, pass them as null
.
_context = new Mock<HrbContext>(null, null);
If you do need them (in other tests etc.), either mock them too or pass real instances through:
var options = new DbContextOptions<HrbContext>(...);
var httpContextAccessor = new HttpContextAccessor(...);
_context = new Mock<HrbContext>(options, httpContextAccessor);