如何让Unity“替换”一个实现用于测试目的

时间:2017-04-06 08:13:19

标签: c# dependency-injection unity-container

我们正在使用Unity for DI,在某些时候,我们有一个完整的初始化过程(发现一些模块,它们正在注册它们的实现)。

我有一个班级<form name="form"> <select class='form-control class-manufacturer' name="" id='id_manufacturer' required> <option value="" selected disabled>Manufacturer *</option> <option value="Apple">Apple</option> <option value="Samsung">Samsung</option> </select> <select class='form-control class-modelName' name="" id="id_modelName" required> <option value="" selected disabled>Model *</option> <option value="Iphone">Iphone</option> <option value="Note">Note</option> </select> <select class='form-control class-partName' name="" id='id_partName' required> <option value="" selected disabled>Part *</option> <option value="IC" >IC</option> <option value="LED">LED</option> </select> <input type="text" name='quantity' id="id_quantity" class="form-control class-quantity" pattern="[0-9]{1,}" maxlength="11" placeholder="Quantity *" required/> <input type="text" name='cost' id="id_costPerUnit" class="form-control class-costPerUnit" pattern="[0-9]{1,}" maxlength="11" placeholder="Price *" required/> <button type="button" class="btn btn-default add-row a" onclick="alert('valid')" style="padding:10px 65px;" disabled>Add</button> </form>,即CommunicationGate。在我的一个集成测试中,我希望DI不返回virtual而是返回CommunicationGate,它来自原始版本,并且有一些虚拟方法覆盖。

这可能吗?怎么样?

1 个答案:

答案 0 :(得分:1)

目前尚不清楚如何设置集成测试环境,但无论您是在测试程序集中,还是使用配置开关,都可以在检测到集成测试时覆盖注册测试环境。例如,一个非常粗略的方法,这样做:

static int Main(string[] args)
{
    UnityContainer container = new UnityContainer();
    UnityRegistrer.Register(container); // Your proper registrations

    bool isIntegratedTest = Super.Logic(); // Get from config, argument, whatever.

    if (isIntegratedTest)
        UnityRegistrerTest.Register(container);

    RestOfTheProgram();
}

public static class UnityRegistrer
{
    public static void Register(IUnityContainer container)
    {
        container.RegisterType<ICommunicationGate, CommunicationGate>("ImplementationOne");
        container.RegisterType<ICommunicationGate, CommunicationGate>("ImplementationTwo",
            new InjectionConstructor(new InjectionParameter<Whatever>("Blah")));
    }
}

public static class UnityRegistrerTest
{
    public static void Register(IUnityContainer container)
    {
        container.RegisterType<ICommunicationGate, CommunicationGateMock>("ImplementationOne");
    }
}

我确实使用ICommunicationGate来推动使用接口注册的议程,但你可以使用基类。 UnityRegistrerTest当然不会出现在您的程序类中,甚至不在同一个程序集中,但我的观点更多的是“您可以覆盖模拟的注册,并保留其他一些注册,即使它们是'只要您使用具有不同名称的命名注册,就可以使用同一个类。“

编辑:如果你使用不同的项目运行集成测试,我会这样做:

// Same UnityRegistrer class is located in the regular library.

// Same UnityRegistrerTest class, but is located in the test assembly.

// In the actual test class where you want to override the registration
[TestClass]
public class WhateverUnitTest
{
    IUnityContainer container;

    [TestInitialize]
    public void TestClassInitialization()
    {
        UnityContainer container = new UnityContainer();
        UnityRegistrer.Register(container);
        UnityRegistrerTest.Register(container);
    }

    [TestMethod]
    public void Blahhhhhh
    {
        //Arrange
        ICommunicationGate communicationGate = container.Resolve<ICommunicationGate>("ImplementationOne");

        //Act
        ...

        //Assert
        ...
    }
}