我有两个完全独立的Asp.Net Core系统,这意味着它们位于不同的Web域中。尽管如此,它们仍然在Visual Studio中使用相同的解决方案。例如,这两个域都将托管Asp.Net Core系统:
https://client-localhost:8080和https://api-localhost:8081
客户端应用程序调用Api域的许多不同路由以获取数据。
我对Api系统进行集成测试(使用NUnit)没有问题,例如:
// Integration Test for the Api
[TestFixture]
class IntegrationTestShould
{
public TestServer GetTestServerInstance()
{
return new TestServer(new WebHostBuilder()
.UseStartup<TestServerStartup>()
.UseEnvironment("TestInMemoryDb"));
}
[Test]
public async Task ReturnProductDataFromTestInMemoryDb()
{
using (var server = GetTestServerInstance())
{
var client = server.CreateClient();
var response = await client.GetAsync("/products"); // equivalent to: https://api-localhost:8081/products
var responseString = await response.Content.ReadAsStringAsync();
Assert.AreEqual("{ Shows product data coming from the Api }", responseString);
}
}
}
为了对客户端应用程序进行适当的集成测试,我想从客户端应用程序向Api进行Api调用。
是否可以创建一个单一的测试方法,我可以在其中启动测试服务器(客户端和Api)并通过我的客户端使用api?
我可以想象,例如,将Api测试服务器注入客户端测试服务器,以便我可以通过我的客户端应用程序使用Api。
是否存在以下内容?
// Integration test for the client that relies on the Api
[TestFixture]
class IntegrationTestShould
{
public TestServer GetApiTestServerInstance()
{
return new TestServer(new WebHostBuilder()
.UseStartup<ApiTestServerStartup>()
.UseEnvironment("TestInMemoryDb"));
}
public TestServer GetClientTestServerInstance()
{
return new TestServer(new WebHostBuilder()
.UseStartup<ClientTestServerStartup>()
.UseEnvironment("Development"));
}
[Test]
public async Task ShowProductsFromApiAtClientLevel()
{
using (var apiServer = GetApiTestServerInstance())
using (var clientServer = GetClientTestServerInstance())
{
var client = clientServer.CreateClient(apiServer);
var response = await client.GetAsync("/products"); // equivalent to: https://client-localhost:8080/products which relies on https://api-localhost:8081/products
var responseString = await response.Content.ReadAsStringAsync();
Assert.AreEqual("{ Shows product data coming from the api at client level }",
responseString);
}
}
}
答案 0 :(得分:0)
感谢mjwills简单但功能强大的问题,我只是按原样测试代码并且存在编译错误。但这让石头滚滚而来,我尝试失败,直到我弄明白。
我基本上做的是将ApiServer的实例化HttpClient注入到我的客户端app后端,其中向ApiServer发出HttpRequest。因此,每当客户端应用程序想要对api服务器进行api调用时,它都会通过使用注入的ApiServer的HttpClient来实现。
以下是我的集成测试和一些我的客户端应用程序代码的快照,任何人都应该指导正确的方向:
// My abbreviated and redacted integration test using NUnit
[TestFixture]
public class IntegrationTestShould
{
public TestServer GetApiTestServerInstance()
{
return new TestServer(new WebHostBuilder()
.UseStartup<ApiTestServerStartup>()
.UseEnvironment("TestInMemoryDb"));
}
public TestServer GetClientTestServerInstance(TestServer apiTestServer)
{
// In order to get views rendered:
// 1. ContentRoot folder must be set when TestServer is built (or views are not found)
// 2. .csproj file of test project must be adjusted, see http://www.dotnetcurry.com/aspnet-core/1420/integration-testing-aspnet-core (or references for view rendering are missing)
var apiHttpClient = apiTestServer.CreateClient();
apiHttpClient.BaseAddress = new Uri(@"https://api-localhost:8081");
var currentDirectory =
Path.GetDirectoryName(Path.GetDirectoryName(TestContext.CurrentContext.TestDirectory));
var contentRoot = Path.GetFullPath(Path.Combine(currentDirectory, @"..\..\ProjectThatContainsViews"));
return new TestServer(new WebHostBuilder()
.UseStartup<ClientTestServerStartup>()
.UseContentRoot(contentRoot)
// register instantiated apiHttpClient in client app
.ConfigureServices(collection => collection.AddSingleton(apiHttpClient))
.UseEnvironment("ClientTestServer"));
}
[Test]
public async Task CorrectlyReturnProductsViewResult()
{
using (var apiServer = GetApiTestServerInstance())
using (var clientServer = GetClientTestServerInstance(apiServer))
{
var clientHttpClient = clientServer.CreateClient();
var response = await clientHttpClient.GetAsync("/products");
var responseString = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Assert.AreEqual("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}
}
// My heavily abbreviated and redacted client app backend
public class HttpRequestBuilder
{
private readonly HttpClient _httpClient;
public HttpRequestBuilder(IServiceProvider serviceProvider)
{
// get instantiated apiHttpClient from client app dependency container (when running in test environment)
// or create new one (the case when running in environment other than test)
_httpClient = serviceProvider.GetService(typeof(HttpClient)) as HttpClient ?? new HttpClient();
}
public async Task<HttpResponseMessage> SendAsync()
{
// Setup request
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(@"https://api-localhost:8081/products")
};
// Send request
var result = await _httpClient.SendAsync(request);
// should have returned product data from api
var content = await result.Content.ReadAsStringAsync();
return result; // api product data processed further at client app level
}
}