简体   繁体   English

如何测试 Ninject 工厂在 RequestScope 中返回相同的实例

[英]How to test a Ninject Factory returns the same instance in RequestScope

In a WebApi application, I am using Ninject to inject a factory that allows consuming classes to create a DbContext that is scoped according to their requirements.在 WebApi 应用程序中,我使用 Ninject 注入一个工厂,该工厂允许使用类创建一个根据其要求确定范围的DbContext I want to be able to write a unit test that verifies that two calls to the same factory for a Request scoped context return the same instance.我希望能够编写一个单元测试来验证对同一工厂的请求范围上下文的两次调用返回相同的实例。

The factory interface is:工厂界面是:

public interface IContextFactory
{
    IMyContext GetContext();
    IMyContext GetTransientContext();
}

The Ninject configuration looks like this: Ninject 配置如下所示:

 Bind<IContextFactory>().ToFactory();
 Bind<IMyContext>().To<MyContext>()
     .InRequestScope()
     .NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
 Bind<IMyContext>().To<MyContext>()
     .InTransientScope()
     .NamedLikeFactoryMethod((IContextFactory f) => f.GetTransientContext());

My unit test is as follows:我的单元测试如下:

[Fact]
public void RequestScopedContextAlwaysSame()
{
    // Arrange
    NinjectWebCommon.Start();
    var factory = (IContextFactory)NinjectWebCommon.Bootstrapper.Kernel.GetService(typeof(IContextFactory));

    //Act
    var context1 = factory.GetContext();
    var context2 = factory.GetContext();

    //Assert
    Assert.Same(context1, context2);
}

I expected the both calls to the factory to return the same instance, but in fact they are two different instances.我希望对工厂的两次调用都返回相同的实例,但实际上它们是两个不同的实例。 I think this is a testing error as in the application, I have been able to successfully verify that the same instance is injected into different consumers when they call the GetContext() method.我认为这是一个测试错误,因为在应用程序中,我已经能够成功验证在调用GetContext()方法时相同的实例被注入到不同的使用者中。

I suspect this is not working in a unit test because there is no HttpContext and InRequestScope() depends on it.我怀疑这在单元测试中不起作用,因为没有HttpContext并且InRequestScope()依赖于它。 Is there a way round this?有没有办法解决这个问题?

I suspect this is not working in a unit test because there is no HttpContext and InRequestScope() depends on it.我怀疑这在单元测试中不起作用,因为没有 HttpContext 并且 InRequestScope() 依赖于它。

I think you are right.我想你是对的。 You may try :你可以试试:

 Bind<IMyContext>().To<MyContext>()
     .InScope(ctx => this.Scope)
     .NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());

where this.Scope is a property of your Test class (any reference type will be ok) the value of which is initialized upon your test setup this.Scope是您的 Test 类的属性(任何引用类型都可以),其值在您的测试设置时初始化

Alternatively, if you still want to use the InRequestScope syntax, you may try :或者,如果您仍想使用 InRequestScope 语法,您可以尝试:

    public class MyPlugin : INinjectHttpApplicationPlugin
    {
        private Object Scope { get; } = true;

        public void Dispose(){}

        public INinjectSettings Settings { get; set; }

        public object GetRequestScope(IContext context)
        {
            return Scope;
        }

        public void Start() { }

        public void Stop() { }
    }

Then your test would be something like :那么您的测试将类似于:

    public void RequestScopedContextAlwaysSame()
    {
        var kernel = new StandardKernel();
        kernel.Components.Add<INinjectHttpApplicationPlugin, MyPlugin>();
        kernel.Bind<IContextFactory>().ToFactory();
        kernel.Bind<IMyContext>().To<MyContext>()
            .InRequestScope()
            .NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
        kernel.Bind<IMyContext>().To<MyContext>()
            .InTransientScope()
            .NamedLikeFactoryMethod((IContextFactory f) => f.GetTransientContext());

        var factory = kernel.Get<IContextFactory>();
        //Act
        var context1 = factory.GetContext();
        var context2 = factory.GetContext();

        //Assert
        Assert.IsTrue(context1.Equals(context2));
    }

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

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