Moles / Fakes:如何实施测试设置?

时间:2012-08-18 10:12:49

标签: unit-testing moles microsoft-fakes

我最近和Moles一起工作,现在我转向Fakes。在我的旧测试项目中,我有一个测试设置,看起来像这样:

[TestInitialize]
public void Setup()
{
    //...
}

在那里,我做了一些必要的设置,就像设置一些我的鼹鼠对象一样。

鼹鼠的测试方法看起来有点像(还有[HostType(“Moles”)]指定它使用鼹鼠对象。

[TestMethod]
[HostType("Moles")]
public void MolesTestMethod()
{
    //...
}

现在,在Fakes中,他们不再使用HostType属性了。相反,他们使用ShimsContext,您可以在其中使用“模拟”类。它看起来像这样:

[TestMethod]
public void FakesTestMethod()
{
    using (ShimsContext.Create())
    {
        //...
    }
}

如果您不使用此上下文,最终可能会收到错误消息。它基本上说FakesTestMethod中有一个ShimInvalidOperationException,你必须按照下面描述的方式使用ShimsContext.Create()。

-- C#:
using Microsoft.QualityTools.Testing.Fakes;

using(ShimsContext.Create())
{
    // your test code using Shims here
}

-- VisualBasic.NET
Imports Microsoft.QualityTools.Testing.Fakes

Using ShimsContext.Create
    ' your test code using Shims here
End Using  

所以我试着把我的设置调用放到那个上下文中,结果是这样的:

[TestInitialize]
public void Setup()
{
    using(ShimsContext.Create())
    {
        //...
    }
}

现在,如果我在我的Setup方法中使用这个上下文,那么在那里完成的所有设置都会在之后的上下文中运行,并且当单元测试实际上即将运行时将不再有效,这实际上并不是什么我想从测试设置方法。

我修复了这个问题,方法是在测试方法本身内部使用use,并在此上下文和测试代码之前调用私有安装方法。此设置方法现在执行所有处理,在[TestInitialize]设置方法之前执行。代码看起来像这样:

[TestMethod]
public void PerformActionFromConfigActionStateActionIdIsSet()
{
    using (ShimsContext.Create())
    {
        Setup();

        //...
    }
}

我现在的问题是,这个解决方案完全“杀死”了[TestInitialize]设置方法的想法。我必须将此代码复制到EACH测试方法和最重要的部分:在这个Setup()方法中创建的对象将被创建并销毁用于EACH测试,这根本不理想!

有没有其他方法可以在Fakes中设置测试数据?任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:12)

Using:

  

定义一个范围,在该范围之外将放置一个或多个对象。

通过调用ShimsContext.Create()创建一个IDisposable实例,并用using块包装它。在初始化Fakes类并离开使用范围后,您的配置将被处理掉。

我建议手动创建IDisposable实例并在测试结束时调用Dispose。

如果你想避免为每个测试创建Context,我还建议使用ClassInitialize和ClassCleanup而不是TestInitialize和TestCleanup,因为它应该足以初始化Shims一次用于alle测试。只有在没有其他依赖项时才可以这样做(参见Oleg Sych的回答)。

[TestClass]
public class TestClass1
{
    protected static IDisposable Context { get; set; }

    [ClassInitialize]
    public static void ClassInitialize(TestContext testContext)
    {
        // Create ShimsContext
        Context = ShimsContext.Create();

        // TODO: Additional setup
    }

    [ClassCleanup]
    public static void ClassCleanup()
    {
        Context.Dispose();
        Context = null;
    }

    [TestMethod]
    public void TestMethod1()
    {
        // Fakes should be initialized correctly here
    }

    [TestMethod]
    public void TestMethod2()
    {
        // Fakes should be initialized correctly here
    }
}

希望有所帮助。

答案 1 :(得分:4)

使用ClassInitialize / ClassCleanup初始化填充程序不是一个好主意。这将使为一个测试方法配置的绕行对于类中的所有其他测试方法保持活动状态。换句话说,弯曲和lambdas捕获的任何其他状态在所有测试方法之间共享。如果您绕开碰巧使用的方法,这也可能会破坏测试工具的稳定性。

相反,使用TestInitialize / TestCleanup分别为每个测试方法创建/处理ShimsContext。