Test .NET6 minimal API with AutoMapper
I have a .NET6 project with minimal APIs. This is the code
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ClientContext>(opt =>
opt.UseInMemoryDatabase("Clients"));
builder.Services
.AddTransient<IClientRepository,
ClientRepository>();
builder.Services
.AddAutoMapper(Assembly.GetEntryAssembly());
var app = builder.Build();
// Get the Automapper, we can share this too
var mapper = app.Services.GetService<IMapper>();
if (mapper == null)
{
throw new InvalidOperationException(
"Mapper not found");
}
app.MapPost("/clients",
async (ClientModel model,
IClientRepository repo) =>
{
try
{
var newClient = mapper.Map<Client>(model);
repo.Add(newClient);
if (await repo.SaveAll())
{
return Results.Created(
$"/clients/{newClient.Id}",
mapper.Map<ClientModel>(newClient));
}
}
catch (Exception ex)
{
logger.LogError(
"Failed while creating client: {ex}",
ex);
}
return Results.BadRequest(
"Failed to create client");
});
This code is working. I have a simple Profile
for AutoMapper
public class ClientMappingProfile : Profile
{
public ClientMappingProfile()
{
CreateMap<Client, ClientModel>()
.ForMember(c => c.Address1, o => o.MapFrom(m => m.Address.Address1))
.ForMember(c => c.Address2, o => o.MapFrom(m => m.Address.Address2))
.ForMember(c => c.Address3, o => o.MapFrom(m => m.Address.Address3))
.ForMember(c => c.CityTown, o => o.MapFrom(m => m.Address.CityTown))
.ForMember(c => c.PostalCode, o => o.MapFrom(m => m.Address.PostalCode))
.ForMember(c => c.Country, o => o.MapFrom(m => m.Address.Country))
.ReverseMap();
}
}
I wrote a NUnit
test and a xUnit
test. In both cases, when I call the API I receive the error
Program: Error: Failed while creating client: AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types: ClientModel -> Client MinimalApis.Models.ClientModel -> MinimalApis.Data.Entities.Client at lambda_method92(Closure , Object , Client , ResolutionContext )
How can I use the Profile in the main project? The full source code is on GitHub.
When you run your project normally, Assembly.GetEntryAssembly()
will resolve to your project's assembly (the one that contains the Profile
classes). When you launch your project via a unit test project, the entry point is actually that unit test.
That means that this code isn't actually finding the profiles because they're not in that assembly:
builder.Services
.AddAutoMapper(Assembly.GetEntryAssembly());
Normally what I do in this situation is to use typeof(someAssemblyInMyProject).Assembly
. In this example I use Program
but any class should work so long as its in the same project as the Profile
classes:
builder.Services
.AddAutoMapper(typeof(Program).Assembly);
Now, no matter what the entry assembly is, you'll still find the right list of profiles.