简体   繁体   English

Ninject依赖注入用于自动化测试

[英]Ninject Dependancy Injection for automated testing

Context: 语境:

I have a WebAPI application that serves multiple Angular applications. 我有一个服务于多个Angular应用程序的WebAPI应用程序。 The WebAPI application uses Ninject to facilitate dependency injection. WebAPI应用程序使用Ninject促进依赖项注入。 We mostly use it in the constructors of the controllers 我们主要在控制器的构造函数中使用它

At the moment the binding looks like this: 目前,绑定看起来像这样:

public static class NinjectWebCommon
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    public static void Start()
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    public static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);
        return kernel;
    }
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IDataContextAsync>().To<StContext>().InRequestScope();

        // FileExtensionService
        kernel.Bind<IFileExtensionService>().To<FileExtensionService>().InRequestScope();
        kernel.Bind<IFileExtensionRepository>().To<FileExtensionRepository>().InRequestScope();
        kernel.Bind<IEntityMapper<Domain.FileExtension, FileExtension>>().To<FileExtensionEntityMapper>().InRequestScope();

        // ...etc
    }
}

An example of a controller would look like this: 控制器的示例如下所示:

[RoutePrefix("api/fileextension")]
public class FileExtensionController : ApiController
{
    private readonly IFileExtensionService service;

    /// <summary>
    /// Initializes a new instance of the <see cref="BestandsextensieController"/> class.
    /// </summary>
    /// <param name="service">The service.</param>
    /// <exception cref="System.ArgumentNullException">service</exception>
    public FileExtensionController(IFileExtensionService service)
    {
        if (service == null)
        { 
            throw new ArgumentNullException(nameof(service));
        }

        this.service = service;
    }

    [HttpGet]
    [Route("getFileextensions")]        
    public IHttpActionResult GetFileExtensions()
    {
        return Ok(service.GetAll());
    }
}

And a Unittest class would look like this: 单元测试类如下所示:

public class FileExtensionControllerTests
{
    private readonly Mock<IFileExtensionService> mockService;

    public FileExtensionControllerTests()
    {
        mockService = new Mock<IFileExtensionService>();
    }

    private FileExtensionController CreateSut()
    {
        return new FileExtensionController(mockService.Object);
    }

    // ... Unittests using CreateSut etc
}

Question

I would like to add automated testing to our Continuous Integration triggers. 我想将自动化测试添加到我们的持续集成触发器中。 In order to do this, we decided to mock the Repositories (using moq, or something custom that just returns fake data). 为此,我们决定模拟存储库(使用moq或仅返回假数据的自定义项)。 Would it be possible to create a conditional situation in which the NinjectWebCommon class injects a mock repository instead of the real one, when it sees it's being called by an automated test? 如果有条件的情况,当NinjectWebCommon类看到自动测试正在调用它时,它会注入一个模拟存储库,而不是真实的存储库?

I don't need any suggestions for mocking, just for Dependancy Injection. 我不需要任何有关模拟的建议,只需依赖注入即可。 Though, feel free to make them anyway if you think I'm doing something wrong. 不过,如果您认为我做错了任何事情,请随时将它们设为。 I just wanted to make sure to set a clear scope. 我只是想确保设置一个明确的范围。

What would be best-practice in this case? 在这种情况下,最佳做法是什么? I'm open for changes to our current way of working if you feel they are appropriate. 如果您认为合适,我愿意改变我们目前的工作方式。

Edit 编辑

So the matter of automated testing is something like Specflow in combination with Selenium. 因此,自动化测试的问题类似于Specflow与Selenium的结合。 The actual clicking of the buttons on the webapp as specified in the specflow tests. 在Specflow测试中指定的Web应用程序上按钮的实际点击。 The only thing different from browsing the site by hand as you normally would, is the "person" controlling the client (browser). 与通常情况下手动浏览站点唯一不同的是,控制客户端(浏览器)的“人”。 Selenium instead of a human being. 硒而不是人类。

Your web application and the unit test application are two different applications. 您的Web应用程序和单元测试应用程序是两个不同的应用程序。 You can just create two different Ninject registrations: 您可以只创建两个不同的Ninject注册:

1) NinjectWebCommon will run when the web application will start 1) NinjectWebCommon将在Web应用程序启动时运行

2) Something like NinjectUnitTestsCommon that will be run by an unit test framework before all tests 2) NinjectUnitTestsCommon东西将在所有测试之前由单元测试框架运行

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

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