我正在编写一些自定义中间件,需要一些服务才能进行注册,我想对其进行单元测试。
中间件基本上捕获所有未处理的异常并记录到持久性存储。在这种特殊情况下,它将被保存到数据库中。
我有一个与商店对话的经理,商店正在注入经理的构造者:
public ErrorManager(IErrorStore<TError, TKey> store)
{
_store = store;
}
我的中间件正在以下列方式注入:
public static AspNetErrorLoggingBuilder<TError, TKey> AddAspNetErrorLogging<TError, TKey>(this IServiceCollection services)
where TError : class, IErrorEntry<TKey>, new()
where TKey : class
{
// Get the object that will hold the configuration.
var aspNetErrorLoggingConfiguration = new AspNetErrorLoggingConfiguration();
// Add all the services that are required.
services.AddSingleton<IErrorStore<TError, TKey>, MemoryErrorStore<TError, TKey>>();
services.TryAddTransient<ErrorManager<TError, TKey>, ErrorManager<TError, TKey>>();
services.AddInstance(aspNetErrorLoggingConfiguration);
// Get the service descriptor of the error store.
var errorStoreDescriptor = services[services.Count - 1];
// Return a builder to configure the DocTrails Power Archive.
return new AspNetErrorLoggingBuilder<TError, TKey>(services, typeof(TError), errorStoreDescriptor);
}
你在这里看到我正在将一个商店的Singleton添加到依赖注入容器中。
现在,在我的单元测试中,我确实创建了一个测试服务器,添加了中间件,并触发了一个导致未处理异常的请求:
public async Task Use_Should_UseMemoryErrorStore()
{
// Defines a provider to retrieve all the registered services.
IServiceProvider serviceProvider = null;
// Create a test server and inject the middleware.
var testServer = TestServer.Create(builder =>
{
builder.UseAspNetErrorLoggingMiddleware<ErrorEntry, string>();
// Defines the response of the server.
builder.Run(context =>
{
throw new Exception("Unhandled exception");
});
}, services =>
{
services.AddAspNetErrorLogging<ErrorEntry, string>();
serviceProvider = services.BuildServiceProvider();
});
// Create the client that can fire requests to the server.
var client = testServer.CreateClient();
// Request a single page (this will cause an exception to be thrown).
await client.GetAsync("/");
}
在调试时,一切似乎都很好,因为异常会被记录到内存中。
当我手动解析依赖关系并对其使用计数时,我得到0;
// Get the Error Manager service and verify that a single entry has been added.
var errorManagerInstance = serviceProvider.GetService<ErrorManager<ErrorEntry, string>>();
var errorsCount = await errorManagerInstance.GetCountAsync();
Assert.Equal(1, errorsCount);
基本上,我通过IServiceProvider
检索的实例与中间件中使用的实例不同,尽管它已注册为Singleton。
如何解决这个问题?
修改
直接注册实例而不是Singleton时,行为似乎有所不同。
var memoryStoreInstance = new MemoryErrorStore<TError, TKey>();
// Add all the services that are required.
services.AddInstance(typeof (IErrorStore<TError, TKey>), memoryStoreInstance);
然后,单元测试通过并使用相同的对象。
亲切的问候