关于c#:Ninject Dependency Injection用于自动化测试

Ninject Dependancy Injection for automated testing

语境:

我有一个WebAPI应用程序,它为多角度应用程序提供服务。webapi应用程序使用ninject来促进依赖项注入。我们主要在控制器的构造器中使用它

目前,绑定如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
    }
}

控制器的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[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());
    }
}

一个UnitTest类如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
}

问题

我想将自动化测试添加到我们的持续集成触发器中。为了做到这一点,我们决定模拟存储库(使用moq,或者一些只返回假数据的定制)。当NinjectWebCommon类看到一个自动测试正在调用它时,是否可以创建一个条件情况,在这种情况下,NinjectWebCommon类将注入一个模拟存储库而不是实际的存储库?

我不需要任何嘲笑的建议,只是为了依赖注射。尽管如此,如果你认为我做错了什么,你还是可以随便做。我只是想确定一个清晰的范围。

在这种情况下,最佳实践是什么?如果你觉得他们合适的话,我愿意改变我们目前的工作方式。

编辑

因此,自动化测试的问题类似于SpecFlow与Selenium的结合。在specFlow测试中指定的webapp上按钮的实际单击。唯一不同于通常的手工浏览站点的是控制客户机(浏览器)的"人"。硒而不是人。


您的Web应用程序和单元测试应用程序是两个不同的应用程序。您可以创建两个不同的Ninject注册:

1)Web应用程序启动时运行NinjectWebCommon

2)类似于NinjectUnitTestsCommon的东西,在所有测试之前由一个单元测试框架运行。