being fairly new to xUnit, I have an application that uses the Unit of Work pattern to return data to a service and I'm trying to unit test this service.
Here is the service code:
public async Task<IEnumerable<CatDto>> GetActiveCatsAsync()
{
var catList = new List<CatDto>();
var catEFList = await _uow.Repository<Cat>().GetActiveCatsAsync();
catList.AddRange(catEFList.Select(c => new CatDto
{
CatId = c.CatId,
CatName = c.CatName,
DisplayOrd = c.DisplayOrd
}));
return catList;
}
And here is the extension that this service calls:
public static async Task<List<Cat>> GetActiveCatsAsync(this IRepository<Cat> repository)
{
return await repository.AsQueryableRepo().Items.Where(c =>c.IsActive == true).OrderBy(c=>c.DisplayOrd).ToListAsync();
}
}
Here is the Interface used by the extension:
internal static IQueryableRepository<T> AsQueryableRepo<T>(this IRepository<T> repository) where T : class
{
return (IQueryableRepository<T>)repository;
}
Here is the concrete unit of work class:
public class SQLUnitOfWork<TContext> : BaseUnitOfWork, ISQLUnitOfWork<TContext>
where TContext : IDbContext, IDisposable
{
public SQLUnitOfWork(TContext context) : base(context)
{
}
}
And here is where I am with a single unit test so far:
[Fact]
public void GetActiveCatsAsync_ReturnsTypeIEnumerableCatDto()
{
var mockLogger = new Mock<ILogger<CatService>>();
var mockUoW = new Mock<ISQLUnitOfWork>();
var catServ = new CatService(mockLogger.Object, mockUoW.Object);
var result = catServ.GetActiveCatsAsync();
Assert.IsType<Task<IEnumerable<CatDto>>>(result);
}
This test actually passes, but obviously the "result" variable has no data in it because there is no setup for the mocks. I also tried setting up:
var mockRepo = new Mock<IRepository<Cat>>();
But this doesn't allow me to get at the extensions methods above. It doesn't show me the "asQueryableRepo()" method to provide a return value for. So I'm not sure how I can mock the return data, which would be a simple Cat object with three properties shown in the service call. I have also tried using xUnit's .ReturnAsync() and Task.FromResult() functionality.
After a few searches, I tried implementing xUnit.DependencyInjection, but that requires configuration in the test project's Startup.cs file. My test project (created with the Visual Studio xUnit project template) doesn't have a Startup.cs file. Did I use the wrong template?
I have also seen something similar to the following used:
scope = new CustomWebApplicationFactory<Startup>().Server.Host.Services.CreateScope();
service = scope.ServiceProvider.GetRequiredService<IDashboardService>();
context = scope.ServiceProvider.GetRequiredService<DTBContext>();
Which also seems to reference a startup class, so I really haven't been able to get this approach working either. Do I need to start again with a project that includes a Startup.cs folder? Or can I Unit Test the code above without it? I'm still researching this, but so far I cannot find a way to mock the dependencies of the service calls and the Unit of Work elements.
Any suggestions or advice is greatly appreciated! Thank you!
UPDATE: I think I now understand the xUnit.DependencyInjection, so I added a startup.cs class, and added the references referred to on their GitHub page. I also had to install Microsoft.Extensions.Hosting package to take care of a "does not have an implementation" error and now my project has a startup and the test that passed above now passes. I'm hoping that I can now handle dependencies within the testing project, but I'll find out.