如何在SimpleInjector 2.6.1+中unit testing开放的通用装饰器链

给定以下使用SimpleInjector的开放式通用deocrator链:

container.RegisterManyForOpenGeneric(typeof(IHandleQuery), assemblies); container.RegisterDecorator( typeof(IHandleQuery), typeof(ValidateQueryDecorator) ); container.RegisterSingleDecorator( typeof(IHandleQuery), typeof(QueryLifetimeScopeDecorator) ); container.RegisterSingleDecorator( typeof(IHandleQuery), typeof(QueryNotNullDecorator) ); 

使用SimpleInjector 2.4.0,我能够使用以下代码对此进行unit testing以断言装饰链:

 [Fact] public void RegistersIHandleQuery_UsingOpenGenerics_WithDecorationChain() { var instance = Container .GetInstance<IHandleQuery>(); InstanceProducer registration = Container.GetRegistration( typeof(IHandleQuery)); instance.ShouldNotBeNull(); registration.Registration.ImplementationType .ShouldEqual(typeof(HandleFakeQueryWithoutValidator)); registration.Registration.Lifestyle.ShouldEqual(Lifestyle.Transient); var decoratorChain = registration.GetRelationships() .Select(x => new { x.ImplementationType, x.Lifestyle, }) .Reverse().Distinct().ToArray(); decoratorChain.Length.ShouldEqual(3); decoratorChain[0].ImplementationType.ShouldEqual( typeof(QueryNotNullDecorator)); decoratorChain[0].Lifestyle.ShouldEqual(Lifestyle.Singleton); decoratorChain[1].ImplementationType.ShouldEqual( typeof(QueryLifetimeScopeDecorator)); decoratorChain[1].Lifestyle.ShouldEqual(Lifestyle.Singleton); decoratorChain[2].ImplementationType.ShouldEqual( typeof(ValidateQueryDecorator)); decoratorChain[2].Lifestyle.ShouldEqual(Lifestyle.Transient); } 

更新到SimpleInjector 2.6.1后,此unit testing失败。 似乎InstanceProducer.Registration.ImplementationType现在返回第一个装饰处理程序而不是装饰处理程序(意思是,它返回typeof(QueryNotNullDecorator)而不是typeof(HandleFakeQueryWithoutValidator)

此外, InstanceProducer.GetRelationships()不再返回链中的所有装饰器。 它也只返回第一个装饰器。

这是一个错误,如果没有,我们如何使用SimpleInjector 2.6.1+unit testing开放的通用装饰链?

依赖图的可用细节在2.6中有了很大的改进。 您可以使用以下代码实现相同的function:

 [Fact] public void RegistersIHandleQuery_UsingOpenGenerics_WithDecorationChain() { var container = this.ContainerFactory(); var instance = container .GetInstance>(); var registration = ( from currentRegistration in container.GetCurrentRegistrations() where currentRegistration.ServiceType == typeof(IHandleQuery) select currentRegistration.Registration) .Single(); Assert.Equal( typeof(QueryNotNullDecorator), registration.ImplementationType); Assert.Equal(Lifestyle.Singleton, registration.Lifestyle); registration = registration.GetRelationships().Single().Dependency.Registration; Assert.Equal( typeof(QueryLifetimeScopeDecorator), registration.ImplementationType); Assert.Equal(Lifestyle.Singleton, registration.Lifestyle); registration = registration.GetRelationships().Single().Dependency.Registration; Assert.Equal( typeof(ValidateQueryDecorator), registration.ImplementationType); Assert.Equal(Lifestyle.Transient, registration.Lifestyle); } 

您可以在此处找到更多信息

请注意:我认为你有一个俘虏依赖 – 你在单件装饰器内有一个瞬态处理程序……

 [Fact] public void Container_Always_ContainsNoDiagnosticWarnings() { var container = this.ContainerFactory(); container.Verify(); var results = Analyzer.Analyze(container); Assert.False(results.Any()); } 

Qujck是对的。 我们极大地改进了注册和KnownDependency图的构建方式,特别是为了改进诊断并使用户更容易查询注册。 所以这不是一个错误; 这是一个突破性的变化。 然而,我们没想到任何人会受到这种影响,这也是我们在次要版本中进行更改的原因。 对不起,你不得不偶然发现这个变化,但至少它只是测试代码打破了。

在以前的版本中,当添加了装饰器时,KnownDependency对象的图形被展平。 这使得难以查询和可视化对象图。 在v2.6中,从诊断API的角度来看,就好像装饰器是“真正的”注册。 这意味着InstanceProducer和Registration对象现在显示返回的真实类型及其生活方式。

更清楚,但诊断API发生了重大变化。