简体   繁体   English

如何在SimpleInjector 2.6.1+中单元测试开放的通用装饰器链

[英]How to unit test open generic decorator chains in SimpleInjector 2.6.1+

Given the following open generic deocrator chain using SimpleInjector: 给定以下使用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<,>)
);

With SimpleInjector 2.4.0, I was able to unit test this to assert the decoration chain using the following code: 使用SimpleInjector 2.4.0,我能够使用以下代码对此进行单元测试以断言装饰链:

[Fact]
public void RegistersIHandleQuery_UsingOpenGenerics_WithDecorationChain()
{
    var instance = Container
        .GetInstance<IHandleQuery<FakeQueryWithoutValidator, string>>();
    InstanceProducer registration = Container.GetRegistration(
        typeof(IHandleQuery<FakeQueryWithoutValidator, string>));

    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<FakeQueryWithoutValidator, string>));
    decoratorChain[0].Lifestyle.ShouldEqual(Lifestyle.Singleton);
    decoratorChain[1].ImplementationType.ShouldEqual(
        typeof(QueryLifetimeScopeDecorator<FakeQueryWithoutValidator, string>));
    decoratorChain[1].Lifestyle.ShouldEqual(Lifestyle.Singleton);
    decoratorChain[2].ImplementationType.ShouldEqual(
        typeof(ValidateQueryDecorator<FakeQueryWithoutValidator, string>));
    decoratorChain[2].Lifestyle.ShouldEqual(Lifestyle.Transient);
}

After updating to SimpleInjector 2.6.1, this unit test fails. 更新到SimpleInjector 2.6.1后,此单元测试失败。 It seems that InstanceProducer.Registration.ImplementationType now returns the first decoration handler rather than the decorated handler (meaning, it returns typeof(QueryNotNullDecorator<HandleFakeQueryWithoutValidator,string>) instead of typeof(HandleFakeQueryWithoutValidator) . 似乎InstanceProducer.Registration.ImplementationType现在返回第一个装饰处理程序而不是装饰处理程序(意思是,它返回typeof(QueryNotNullDecorator<HandleFakeQueryWithoutValidator,string>)而不是typeof(HandleFakeQueryWithoutValidator)

Also, InstanceProducer.GetRelationships() no longer returns all of the decorators in the chain. 此外, InstanceProducer.GetRelationships()不再返回链中的所有装饰器。 it also only returns the first decorator. 它也只返回第一个装饰器。

Is this a bug and, if not, how can we unit test open generic decorator chains using SimpleInjector 2.6.1+? 这是一个错误,如果没有,我们如何使用SimpleInjector 2.6.1+单元测试开放的通用装饰链?

The detail available for the dependency graph has been greatly improved in 2.6. 依赖图的可用细节在2.6中有了很大的改进。 You can achieve the same thing with this code: 您可以使用以下代码实现相同的功能:

[Fact]
public void RegistersIHandleQuery_UsingOpenGenerics_WithDecorationChain()
{
    var container = this.ContainerFactory();

    var instance = container
        .GetInstance<IHandleQuery<FakeQueryWithoutValidator, string>>();

    var registration = (
        from currentRegistration in container.GetCurrentRegistrations()
        where currentRegistration.ServiceType ==
            typeof(IHandleQuery<FakeQueryWithoutValidator, string>)
        select currentRegistration.Registration)
        .Single();
    Assert.Equal(
        typeof(QueryNotNullDecorator<FakeQueryWithoutValidator, string>), 
        registration.ImplementationType);
    Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);

    registration = registration.GetRelationships().Single().Dependency.Registration;
    Assert.Equal(
        typeof(QueryLifetimeScopeDecorator<FakeQueryWithoutValidator, string>), 
        registration.ImplementationType);
    Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);

    registration = registration.GetRelationships().Single().Dependency.Registration;
    Assert.Equal(
        typeof(ValidateQueryDecorator<FakeQueryWithoutValidator, string>), 
        registration.ImplementationType);
    Assert.Equal(Lifestyle.Transient, registration.Lifestyle);
}

You can find more information here 您可以在此处找到更多信息

Please note: I think you have a captive dependency - you have a transient handler inside of a singleton decorator ... 请注意:我认为你有一个俘虏依赖 - 你在单身装饰器内有一个瞬态处理程序......

[Fact]
public void Container_Always_ContainsNoDiagnosticWarnings()
{
    var container = this.ContainerFactory();

    container.Verify();

    var results = Analyzer.Analyze(container);

    Assert.False(results.Any());
}

Qujck is right. Qujck是对的。 We greatly improved the way registrations and KnownDependency graphs are built, especially to improve diagnostics and to make it easier for users to query the registrations. 我们极大地改进了注册和KnownDependency图的构建方式,特别是改进了诊断并使用户更容易查询注册。 So this is not a bug; 所以这不是一个bug; this is a breaking change. 这是一个突破性的变化。 We however didn't expect anyone to be affected by this and that's why we made the change in a minor release. 然而,我们没想到任何人会受到这种影响,这就是为什么我们在次要版本中进行了更改。 I'm sorry you had to stumble upon this change, but at least it's just test code that breaks. 对不起,你不得不偶然发现这个变化,但至少它只是破坏的测试代码。

In previous versions the graph of KnownDependency objects was flattened when decorators where added. 在以前的版本中,当添加了装饰器时,KnownDependency对象的图形被展平。 This made querying and visualising the object graph hard. 这使得难以查询和可视化对象图。 In v2.6, from perspective of the diagnostic API, it is as if a decorator is a 'real' registration. 在v2.6中,从诊断API的角度来看,就好像装饰器是“真正的”注册。 This means that the InstanceProducer and Registration objects now show the real type that is returned and its lifestyle. 这意味着InstanceProducer和Registration对象现在显示返回的真实类型及其生活方式。

Much clearer, but a breaking change in the diagnostic API. 更清楚,但诊断API发生了重大变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM