#c# #asp.net-core #integration-testing
Вопрос:
Я использую Microsoft ASP.NET Основная статья по тестированию интеграции и Moq.Contrib.Пример проекта HttpClient .NET 5 для настройки проекта IntegrationTest. Мое настоящее приложение и тестовый проект-.NET Core 3.1. Я получаю ошибку в конструкторе:
Не знаю, в чем тут проблема. Вот тестовый класс:
using FluentAssertions;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Moq.Contrib.HttpClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;
namespace API.IntegrationTests
{
// This shows how you can mock HttpClient at the service collection level in integration tests. Note: "factory" and
// "client" here are part of the integration test framework, TestServer, not our mock. For more info on integration
// tests in ASP.NET Core, see https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests
public class ExampleTests : IClassFixture<CustomWebApplicationFactory<Startup>>
{
private readonly CustomWebApplicationFactory<Startup> factory;
private readonly Mock<HttpMessageHandler> githubHandler = new Mock<HttpMessageHandler>();
public ExampleTests(CustomWebApplicationFactory<Startup> factory)
{
this.factory = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
// This will configure the "github" named client to use our mock handler while keeping the default
// IHttpClientFactory infrastructure and any configurations made in Startup intact (as opposed to
// replacing the IHttpClientFactory implementation outright). This will work with typed clients,
// too. For the default (unnamed) client, use `Options.DefaultName`.
services.AddHttpClient("github")
.ConfigurePrimaryHttpMessageHandler(() => githubHandler.Object);
});
});
}
[Fact]
public async Task GetReposTest()
{
// This is the integration test client used to make requests against the ASP.NET Core app under test
var client = factory.CreateClient();
var mockRepos = new GitHubRepository[]
{
new GitHubRepository()
{
Name = "Foo",
Language = "TypeScript",
Stars = 39
},
new GitHubRepository()
{
Name = "Bar",
Language = "C#",
Stars = 9001 // It's over 9000!!!
}
};
var expectedResponse =
"Foo (TypeScript, ★39)n"
"Bar (C#, ★9001)n";
// Notice there was no need to set a BaseAddress in this test class. All of the dependency injection and the
// AddHttpClient() in ConfigureServices() are essentially unchanged and working as they would normally.
githubHandler.SetupRequest(HttpMethod.Get, "https://api.github.com/users/maxkagamine/repos")
.ReturnsResponse(JsonConvert.SerializeObject(mockRepos), "application/vnd.github.v3 json");
var response = await client.GetStringAsync("/");
response.Should().Be(expectedResponse,
"the app's requests should hit the mock handler now instead of the real API");
}
}
}
А вот и CustomWebApplicationFactory
:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Linq;
namespace API.IntegrationTests
{
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbContextOptions<ApplicationDBContext>));
services.Remove(descriptor);
//services.AddDbContext<ApplicationDBContext>(options =>
//{
// options.UseInMemoryDatabase("InMemoryDbForTesting");
//});
var sp = services.BuildServiceProvider();
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ApplicationDBContext>();
var logger = scopedServices
.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();
db.Database.EnsureCreated();
//try
//{
// Utilities.InitializeDbForTests(db);
//}
//catch (Exception ex)
//{
// logger.LogError(ex, "An error occurred seeding the "
// "database with test messages. Error: {Message}", ex.Message);
//}
}
});
}
}
}