ross
ross
CC#
Created by ross on 9/25/2022 in #help
Dotnet code generator web api question
I've been trying out the API code generator in visual studio/dotnet, and I had a question about some of the CRUD methods it generates:
// POST: api/VehicleController
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<Vehicle>> PostMagnet(Vehicle vehicle)
{
if (_context.Vehicles == null)
{
return Problem("Entity set 'Context.Vehicles' is null.");
}
_context.Vehicles.Add(vehicle);
await _context.SaveChangesAsync();

return CreatedAtAction("GetVehicle", new { id = vehicle.Id }, vehicle);
}
// POST: api/VehicleController
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<Vehicle>> PostMagnet(Vehicle vehicle)
{
if (_context.Vehicles == null)
{
return Problem("Entity set 'Context.Vehicles' is null.");
}
_context.Vehicles.Add(vehicle);
await _context.SaveChangesAsync();

return CreatedAtAction("GetVehicle", new { id = vehicle.Id }, vehicle);
}
What's the purpose of checking if _context.Vehicles == null? Like I understand that you obviously won't be able to add and saveChanges if it were null, but I can't think of a circumstance where it would be null and that check would apply? I see that check is done in Get, GetById, Post, and Delete. Just curious!
14 replies
CC#
Created by ross on 9/21/2022 in #help
[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:
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 = "[email protected]" });
_db.Users.Add(new User { Id = 2, FirstName = "Christie", Surname = "Wickson", Email = "[email protected]" });
_db.Users.Add(new User { Id = 3, FirstName = "Leanna", Surname = "Burnes", Email = "[email protected]" });
_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 = "[email protected]" });
_db.Users.Add(new User { Id = 2, FirstName = "Christie", Surname = "Wickson", Email = "[email protected]" });
_db.Users.Add(new User { Id = 3, FirstName = "Leanna", Surname = "Burnes", Email = "[email protected]" });
_db.SaveChanges();
}

return dbContextOptions;
}
}
So, am I doing anything wrong?
14 replies
CC#
Created by ross on 9/15/2022 in #help
Multiple classes defining same props vs inherit from base class
Say I have multiple service classes, here's two as an example:
public class FooService {

private readonly DbContext _db;
private readonly ILogger<FooService> _logger;

public FooService(DbContext db, ILogger<FooService> logger) {
_db = db;
_logger = logger;
}
}

public class BarService {

private readonly DbContext _db;
private readonly ILogger<FooService> _logger;

public BarService(DbContext db, ILogger<BarService> logger) {
_db = db;
_logger = logger;
}
}
public class FooService {

private readonly DbContext _db;
private readonly ILogger<FooService> _logger;

public FooService(DbContext db, ILogger<FooService> logger) {
_db = db;
_logger = logger;
}
}

public class BarService {

private readonly DbContext _db;
private readonly ILogger<FooService> _logger;

public BarService(DbContext db, ILogger<BarService> logger) {
_db = db;
_logger = logger;
}
}
Instead of repeating the two private properties and the ctor on every service class, would it be acceptable to create a base class which the service classes inherit from? E.g:
public class BaseService {

public readonly DbContext _db;
public readonly ILogger<BaseService> _logger;

public BaseService(DbContext db, ILogger<BaseService> logger) {
_db = db;
_logger = logger;
}
}

public class FooService {

public FooService(DbContext db, ILogger<BaseService> logger) : base(db, logger)
{
}
}

public class BarService{

public BarService(DbContext db, ILogger<BaseService> logger) : base(db, logger)
{
}
}
public class BaseService {

public readonly DbContext _db;
public readonly ILogger<BaseService> _logger;

public BaseService(DbContext db, ILogger<BaseService> logger) {
_db = db;
_logger = logger;
}
}

public class FooService {

public FooService(DbContext db, ILogger<BaseService> logger) : base(db, logger)
{
}
}

public class BarService{

public BarService(DbContext db, ILogger<BaseService> logger) : base(db, logger)
{
}
}
I'm just approaching this from a DRY point of view. Technically I'm still repeating myself with the ctor in every service class, but it just seems cleaner? Some guidance would be much appreciated
6 replies