【问题标题】:Using Castle Windsor in Unit Test Class在单元测试类中使用 Castle Windsor
【发布时间】:2016-04-28 19:35:13
【问题描述】:

我是温莎城堡的菜鸟。我正在构建一个使用 Entity Framework 6 和 Castle Windsor 以及 MSTest 单元测试类的应用程序。我的应用程序中有一个实现IWindsorInstaller 的类。我的单元测试类如下所示:

[TestClass]
public class DatabaseTests {

    static readonly WindsorContainer Container = new WindsorContainer();

    public DatabaseTests() {
        Container.Install( FromAssembly.This() );
    }

    [TestMethod]
    public void FirstTest() {
        // Test statements
    }

    [TestMethod]
    public void SecondTest() {
        // Test statements
    }

    // Other tests
}

单元测试项目中还有一个安装程序类,如下所示:

public class TestsInstaller : IWindsorInstaller {
    public void Install( IWindsorContainer container, IConfigurationStore store ) {
        container.Install( new RecipeManager.RepositoriesInstaller() );
    }
}

当我进入 Unit Test Session 窗口并尝试运行所有测试时,第一个测试成功,其余的我得到这个堆栈跟踪:

无法创建 UnitTests.DatabaseTests 类的实例。错误:Castle.MicroKernel.ComponentRegistrationException:无法注册组件 RecipeManager.DAL.CategoryRepository。已经有一个具有该名称的组件。您是否想修改现有组件?如果没有,请确保您指定一个唯一的名称.. 在 Castle.MicroKernel.SubSystems.Naming.DefaultNamingSubSystem.Register(IHandler 处理程序) 在 Castle.MicroKernel.DefaultKernel.AddCustomComponent(ComponentModel 模型) 在 Castle.MicroKernel.DefaultKernel.Register(IRegistration[] 注册) 在 Castle.Windsor.WindsorContainer.Register(IRegistration[] 注册) 在 C:\Users\Tony\documents\visual studio 2015\Projects\RecipeManager\ManageRecipes\RepositoriesInstaller.cs:line 10 中的 RecipeManager.RepositoriesInstaller.Install(IWindsorContainer 容器,IConfigurationStore 存储) 在 Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] 安装程序,DefaultComponentInstaller 范围) 在 Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] 安装程序) 在 C:\Users\Tony\documents\visual studio 2015\Projects\RecipeManager\UnitTests\TestsInstaller.cs:line 8 中的 UnitTests.TestsInstaller.Install(IWindsorContainer 容器,IConfigurationStore 存储) 在 Castle.Windsor.Installer.AssemblyInstaller.Install(IWindsorContainer 容器,IConfigurationStore 商店) 在 Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] 安装程序,DefaultComponentInstaller 范围) 在 Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] 安装程序) 在 C:\Users\Tony\documents\visual studio 2015\Projects\RecipeManager\UnitTests\DatabaseTests.cs:line 17 中的 UnitTests.DatabaseTests..ctor() 中

如果我一次运行一个单元测试,它们都会成功。我打算构建大量测试,所以我真的宁愿能够一次运行它们。我该如何解决这个问题?

【问题讨论】:

  • 我想知道如果使用 Castle 来处理依赖注入进行测试实际上是一个坏主意。 1)它违反了单元测试的自文档原则,因为现在隐藏了依赖项,并且 2)如果您更改了依赖项,您的代码仍然可以编译,可能会使代码未被发现。

标签: c# .net unit-testing castle-windsor


【解决方案1】:

在您的测试类中,创建一个字段。

private WindsorContainer Container;

(替换现有的静态字段。)

然后,将其添加到您的测试类中:

[TestInitialize]
public void SetUp()
{
    Container = new WindsorContainer();
    // register your dependencies
}

[TestCleanup]
public void Cleanup()
{
    Container.Dispose();
}

[TestInitialize] 在每次测试前运行,[TestCleanup] 在每次测试后运行。
这样,您就不会为每个测试重用相同的容器并尝试使用该容器重新注册相同的依赖项。在运行每个测试之前,您将创建一个新容器。如果每个测试都需要相同的依赖项,可以在Setup() 中注册它们。或者,如果需要,您可以在测试方法中注册它们。

【讨论】:

  • 当我说你的弹出窗口时,我只是点击了post your answer。我没有假点,你也有一些假点
  • 我其实不知道那是什么意思。我们为此获得积分?
【解决方案2】:

要升级一下这个答案: 我创建了一个包含 Windsor Container 逻辑的 Base RepositoryTest 类。该类成为所有单元测试类的根。

public abstract class RepositoryTestBase
{
    private static IWindsorContainer windsorContainer { get; set; }
    private static IMapper mapper { get; set; }

    protected static IWindsorContainer WindsorContainer
    {
        get
        {
            if (windsorContainer == null)
            {
                WindsorContainerManager.ConfigureWindsor(Assembly.GetExecutingAssembly());
                windsorContainer = WindsorContainerManager.Container;
            }
            return windsorContainer;
        }
    }

    protected IMapper Mapper
    {
        get
        {
            if (mapper == null)
            {
                mapper = WindsorContainer.Resolve<IMapper>();
            }
            return mapper;
        }
    }

    public static T GetResolved<T>()
    {
        return WindsorContainer.Resolve<T>();
    }
}

    [TestFixture, Category("UnitTest")]
public class AccountRepositoryTests : RepositoryTestBase
{
    private IAccountRepository accountRepo = GetResolved<IAccountRepository>();
    private IContactRepository contactRepo = GetResolved<IContactRepository>();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多