WebApplicationFactory for BaseTest class
There are many ways we can structure our tests. Here is a small example to get started! Using this base class, we are trying to test our system from out user's perspective.
public abstract class BaseWebApplicationFactory<TProgram> : IClassFixture<WebApplicationFactory<TProgram>> where TProgram : class
{
protected readonly HttpClient Client;
private readonly WebApplicationFactory<TProgram> _factory;
private readonly SqliteConnection _connection;
protected IServiceProvider ServiceProvider; // usage: var uowService = ServiceProvider.GetRequiredService<IUnitOfWork>(); var books = await uowService.BookRepository.GetAll().FirstAsync();
protected BaseWebApplicationFactory(WebApplicationFactory<TProgram> factory)
{
_factory = factory;
_connection = new SqliteConnection("DataSource=:memory:");
_connection.Open(); Client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
// Remove the existing context configuration if any
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>));
if (descriptor != null)
services.Remove(descriptor); // Add ApplicationDbContext using SQLite in-memory database
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlite(_connection);
}); // Add other necessary services like IUnitOfWork, IMapper, IMediator, ICreateLinks etc.
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddAutoMapper(typeof(Program));
services.AddMediatR(m => m.RegisterServicesFromAssemblyContaining<Program>());
// Add your services and repository here
services.AddScoped<IBookRepository, BookRepository>();
services.AddScoped<ICreateLinks, CreateLinks>(); // Ensure the database is created and migrated before running tests
ServiceProvider = services.BuildServiceProvider();
using var scope = ServiceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
db.Database.EnsureCreated();
});
}).CreateClient();
} public void Dispose()
{
_connection.Close();
// _connection.Dispose();
}
}
The usage:
public class BooksControllerWebAppTests: BaseWebApplicationFactory<Program>
{
public BooksControllerWebAppTests(WebApplicationFactory<Program> factory) : base(factory)
{
}
[Fact]
public async Task GetBooks()
{
// Arrange & Act
var response = await Client.GetAsync("/books");
// Assert: Check that the response status code is 200 OK
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
// Optionally, deserialize response content
var books = JsonConvert.DeserializeObject<List<Book>>(responseString);
Assert.NotNull(books);
Assert.NotEmpty(books);
}
[Fact]
public async Task GetById()
{
// Arrange
// alternative using the service
// var uowService = ServiceProvider.GetRequiredService<IUnitOfWork>();
// var books = await uowService.BookRepository.GetAll().FirstAsync();
var bookInDb = DefaultData.DefaultBooks.First();
Assert.NotNull(bookInDb);
// Act
var response = await Client.GetAsync($"/books/id/{bookInDb.Id}");
// Assert: Check that the response status code is 200 OK
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
var bookResponse = JsonConvert.DeserializeObject<Book>(responseString);
Assert.NotNull(bookResponse);
Assert.Equal(bookInDb.Id, bookResponse.Id);
Assert.Equal(bookInDb.Isbn, bookResponse.Isbn);
}
[Fact]
public async Task GetById_NotFound()
{
// Arrange & Act
var response = await Client.GetAsync($"/id/{Guid.Empty}");
// Assert: Check that the response status code is 404 OK
Assert.Equal(404, (int)response.StatusCode);
}
// Add more tests...
}
No files yet, migration hasn't completed yet!