マイクロサービス環境では、契約ベースのテスト用のフレームワークを構築する必要があります。私は現在、プロバイダー テストを実行するために、単一のサービスを外部依存関係から分離する方法を調査しています。
私がする必要があるのは:
- WebApi プロジェクトをそのまま維持する
- いくつかの構成の違いを使用して WepApi のインスタンスを開始します
- 選択した依存関係をモックアウトする
私のソリューション構造はこれです:
Case-Solution/
├── src/
| ├──Case.Api
| └──Case.Application
├── test/
| ├──Case.Api.Unittest
| ├──(other tests)
| ├──Case.Pact.CunsumerTest
| └──Case.Pact.ProviderTest
dotnet での Pact テストに関するこのガイドを読みました。に焦点を当てると、プログラムで(および Pact 自体の別の WebHost)からCase.Pace.ProviderTest
開始し、その依存関係の一部を置き換える必要があります。Case.Api
Case.Pact.ProviderTest
これまでのところ、私はこれを得ました:
public class ProviderApiTests : IDisposable
{
private string ProviderUri { get; }
private string PactServiceUri { get; }
private IWebHost PactServiceWebHost { get; }
private IWebHost CasesWebHost { get; }
private ITestOutputHelper OutputHelper { get; }
public static IConfiguration CaseConfiguration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT" ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();
public ProviderApiTests(ITestOutputHelper output)
{
OutputHelper = output;
ProviderUri = "http://localhost:9000";
PactServiceUri = "http://localhost:9001";
CasesWebHost = WebHost.CreateDefaultBuilder()
.UseUrls(ProviderUri)
.UseStartup<CaseStartup>()
.UseConfiguration(CaseConfiguration)
.Build();
CasesWebHost.Start();
PactServiceWebHost = WebHost.CreateDefaultBuilder()
.UseUrls(PactServiceUri)
.UseStartup<ProviderServerStartup>()
.Build();
PactServiceWebHost.Start();
}
[Fact]
public void EnsureProviderApiHonoursPactWithConsumer()
{
//Arrange
var config = new PactVerifierConfig
{
Outputters = new List<IOutput>
{
new XUnitOutput(OutputHelper)
},
Verbose = true,
CustomHeader = new KeyValuePair<string, string>("X-apikey", "XXX")
};
//Act //Assert
IPactVerifier pactVerifier = new PactVerifier(config);
pactVerifier.ProviderState($"{PactServiceUri}/provider-states")
.ServiceProvider("CaseProvider", ProviderUri)
.HonoursPactWith("CaseConsumer")
.PactUri(@"..\..\..\..\..\pacts\caseconsumer-caseprovider.json")
.Verify();
}
#region IDisposable Support
//IDisposable code
#endregion
}
を含む行では、必要な依存関係を.UseStartup<CaseStartup>()
単純にコピーStartup.cs
して変更しましたが、これは正常に機能します。Case.Api
しかし、より一般的なソリューションが必要です。コードをコピーして 1 日で終了するのは適切ではありません :) これは、他のサービスで一般的ではなく、再利用可能ではないためです。
それで私は掘り続け、次のことを思いつきました。
別のアセンブリ
から StartUp を使用して IWebhost を開始しても、そのアセンブリからコントローラーが自動的に追加されないことに気付きました。これは明示的に行う必要があります。だから私はこれをしました:
public void ConfigureServices(IServiceCollection services)
{
var assembly = Assembly.Load("Case.Api");
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddApplicationPart(assembly)
.AddControllersAsServices();
......
}
素晴らしい!!!ここまでは順調ですね。
次号:
依存関係を置き換える:この
記事を
読み直して、依存関係を置き換えるための拡張メソッドを作成しました。
public static void Replace<TRegisteredType>(this IServiceCollection services, TRegisteredType replcement)
{
for (var i = 0; i < services.Count; i++)
{
if (services[i].ServiceType == typeof(TRegisteredType))
{
services[i] = new ServiceDescriptor(typeof(TRegisteredType), replcement);
}
}
}
したがって、必要な依存関係を次のように置き換えることができます: (この場合は QueryHandler)
public void ConfigureServices(IServiceCollection services)
{
.....
var queryHandler = Substitute.For<IQueryHandler<Query, QueryResult>>();
queryHandler.Handle(Arg.Any<Query>()).Returns(new QueryResult(...));
services.Replace(queryHandler);
......
}
しかし、これはコピーされたコードに関する私の問題を解決しません。
私の甘い夢は、すべての冗長なコードを持たずに、依存関係を置き換えるためにfrom を使用Startup.cs
し、何らかの方法で DI を微調整できるようにすることです。Case.Api
どんな入力も非常に高く評価されます。
ありがとう :)