[XUnit, Moq, EFCore] Unit Testing Question
Hi folks, needing some advice on this approach. This is my first real go at unit testing, so wanted to make sure I'm off in the right direction.
My app works as so: Frontend calls API, API calls service class, service class has direct access to dbContext. Simples.
So here's an example of one of my service classes and a method, and the unit test:
Service class:
Test class:
So, am I doing anything wrong?
My app works as so: Frontend calls API, API calls service class, service class has direct access to dbContext. Simples.
So here's an example of one of my service classes and a method, and the unit test:
Service class:
public class UserService : BaseService
{
public UserService(AppNameDbContext db, ILogger<BaseService> logger) : base(db, logger)
{
}
/// <summary>
/// Get all users async
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<UserDto>> GetAllAsync()
{
try
{
var users = await _db.Users.ToListAsync();
if (users is not null)
{
// TODO: Create extension method for mapping
var dto = new List<UserDto>();
foreach (var user in users)
{
dto.Add(new UserDto
{
Id = user.Id,
Email = user.Email,
FirstName = user.FirstName,
Surname = user.Surname,
});
}
return dto;
}
throw new NullReferenceException(nameof(users));
}
catch (Exception)
{
throw;
}
}
}public class UserService : BaseService
{
public UserService(AppNameDbContext db, ILogger<BaseService> logger) : base(db, logger)
{
}
/// <summary>
/// Get all users async
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<UserDto>> GetAllAsync()
{
try
{
var users = await _db.Users.ToListAsync();
if (users is not null)
{
// TODO: Create extension method for mapping
var dto = new List<UserDto>();
foreach (var user in users)
{
dto.Add(new UserDto
{
Id = user.Id,
Email = user.Email,
FirstName = user.FirstName,
Surname = user.Surname,
});
}
return dto;
}
throw new NullReferenceException(nameof(users));
}
catch (Exception)
{
throw;
}
}
}Test class:
public class UserServiceTest
{
[Fact]
public void GetAll_ShouldPass()
{
var dbContextOptions = SetupTestDatabase();
var mockLogger = Mock.Of<ILogger<BaseService>>();
using (var mockDb = new AppNameDbContext(dbContextOptions))
{
var userService = new UserService(mockDb, mockLogger);
var result = userService.GetAllAsync(); // not calling await here, i know. 1 step at a time
Assert.Equal(3, result.Result.Count());
}
}
private DbContextOptions<AppNameDbContext> SetupTestDatabase()
{
var dbContextOptions = new DbContextOptionsBuilder<AppNameDbContext>()
.UseInMemoryDatabase("UnitTestDatabase")
.Options;
using (var _db = new AppNameDbContext(dbContextOptions))
{
// https://www.mockaroo.com/
_db.Users.Add(new User { Id = 1, FirstName = "Cornelle", Surname = "Dyett", Email = "cdyett0@ocn.ne.jp" });
_db.Users.Add(new User { Id = 2, FirstName = "Christie", Surname = "Wickson", Email = "cwickson1@smugmug.com" });
_db.Users.Add(new User { Id = 3, FirstName = "Leanna", Surname = "Burnes", Email = "lburnes2@liveinternet.ru" });
_db.SaveChanges();
}
return dbContextOptions;
}
}public class UserServiceTest
{
[Fact]
public void GetAll_ShouldPass()
{
var dbContextOptions = SetupTestDatabase();
var mockLogger = Mock.Of<ILogger<BaseService>>();
using (var mockDb = new AppNameDbContext(dbContextOptions))
{
var userService = new UserService(mockDb, mockLogger);
var result = userService.GetAllAsync(); // not calling await here, i know. 1 step at a time
Assert.Equal(3, result.Result.Count());
}
}
private DbContextOptions<AppNameDbContext> SetupTestDatabase()
{
var dbContextOptions = new DbContextOptionsBuilder<AppNameDbContext>()
.UseInMemoryDatabase("UnitTestDatabase")
.Options;
using (var _db = new AppNameDbContext(dbContextOptions))
{
// https://www.mockaroo.com/
_db.Users.Add(new User { Id = 1, FirstName = "Cornelle", Surname = "Dyett", Email = "cdyett0@ocn.ne.jp" });
_db.Users.Add(new User { Id = 2, FirstName = "Christie", Surname = "Wickson", Email = "cwickson1@smugmug.com" });
_db.Users.Add(new User { Id = 3, FirstName = "Leanna", Surname = "Burnes", Email = "lburnes2@liveinternet.ru" });
_db.SaveChanges();
}
return dbContextOptions;
}
}So, am I doing anything wrong?