我的CompositionRoot靜態類有一個測驗夾具,它幾乎只是列舉我的 AutofacIContainer的服務并嘗試實體化它們。如果它可以實體化它們,那就是測驗通過。目標是確保我不會忘記向我的 Autofac 容器注冊新介面。
但是,某些已注冊的型別在其建構式中使用不打算或不能在 Autofac 中注冊的型別。例如,我有一個string在其建構式中采用 a 的類。我將這個類注入我的代碼庫的方式是:
Func<string, ITypeThatRequiresAFactory>
這是我的測驗夾具(使用 NUnit3 FluentAssertions):
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class CompositionRootTest
{
private sealed class ConcreteTypeEnumerator : IEnumerable
{
private readonly IContainer _container;
public ConcreteTypeEnumerator()
{
_container = CompositionRoot.Setup();
}
public IEnumerator GetEnumerator()
{
return _container.ComponentRegistry.Registrations
.SelectMany(x => x.Services)
.OfType<TypedService>()
.GetEnumerator();
}
}
[TestCaseSource(typeof(ConcreteTypeEnumerator))]
public void Service_should_be_instantiable(Service service)
{
using var container = CompositionRoot.Setup();
container.Invoking(c => c.ResolveService(service))
.Should().NotThrow()
.And.NotBeNull();
}
}
由于建構式中的引數,Service_should_be_instantiable當它嘗試實體化服務實作時,測驗將失敗。ITypeThatRequiresAFactorystring
如何將我的測驗夾具重構為:
- 表達明確測驗型別的串列
- 哪些被排除在測驗的型別串列中
Service_should_be_instantiable - 并且必須撰寫一個手動測驗用例來驗證它們是否可以解決(很可能使用特殊的復合型別,比如
Func<>)?
目標是使用 Autofac 的隱式關系型別用于自動工廠 ( Func<>) 以及以后可能的其他隱式關系 (如Lazy<>),因此,例如,需要我顯式注冊手寫工廠的解決方案是行不通的。
uj5u.com熱心網友回復:
你需要做的是:
- 決議型別而不是服務,以便您可以排除所需的型別。
- 洗掉重復項(因此,如果您注冊了兩件事
.As<IFoo>(),您將不會運行該測驗兩次)。 - 排除
Autofac型別(因為ILifetimeScope和IComponentContext是固有注冊的,不應該成為測驗的一部分)。
該 LINQ 看起來像:
var exclude = new []
{
typeof(ThingToSkip),
typeof(OtherThingToSkip),
};
// Get all the registrations
// Pull out the services
// Only look at typed (reflection) services
// Get the actual type from the service
// Filter down to unique types
// Exclude the types you don't want to test
// Exclude the Autofac types
var typesToTest = container.ComponentRegistry.Registrations
.SelectMany(x => x.Services)
.OfType<TypedService>()
.Select(t => t.ServiceType)
.Distinct()
.Except(exclude)
.Where(t => !t.FullName.StartsWith("Autofac."));
您的決議行將更改為:
container.Resolve(type);
...因為您將根據型別而不是服務進行決議。
我認為這應該能讓你到達你要去的地方。
請注意,這不會涵蓋...
- 開放泛型
IEnumerable<T>,Func<T>, 或 Autofac 支持的任何其他“內置關系”- 任何注冊為 lambda
ILifetimeScope決議或決議后可能在建構式內完成的服務位置IComponentContext
...等等。我的意思是,你可能明白了,因為你已經在過濾了,TypedService但我想我會很明確。這是 Autofac 中沒有內置這樣的東西的主要原因——人們會認為我們有能力檢查所有的注冊,這實際上是不可能的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/421464.html
標籤:
上一篇:如何測驗服務或正確模擬?Java11、Spock框架
下一篇:如何模擬django模型物件?
