微软摩尔,动态仪器

时间:2011-06-07 22:12:15

标签: c# .net moles

Moles可以通过两种方式使用:

手动

  1. 包括[assembly:MoledType(typeof(_type_to_instrument))]
  2. 指定[HostType(“Moles”)]
  3. 调用Microsoft.Moles.Framework.Moles.MoleRuntime.SetMole(委托_stub,object _receiver,MethodInfo方法);
  4. 动态

    1. 添加{project name} .moles文件:指定assembly to mole。例如 <Moles xmlns="http://schemas.microsoft.com/moles/2010/"> <Assembly Name="Samples.Moles"/> </Moles>
    2. 构建并包含对MolesAssemblies / {project_name} .Moles.dll
    3. 的引用
    4. 使用M {class_name}自动生成的分类。
    5. 我注意到使用动态程序集不需要测试项目声明'moled assemblies'属性。这减少了开销,开发人员只需要使用主机类型为每个测试方法装饰摩尔;但进一步测试不需要跟踪要测量的类型。

      查看molesassemblies中自动生成的代码(使用反汇编程序),很容易找到所需的检测属性。然而,尝试编写我自己的'mole assembly',基本上替换自动生成的那个,并不起作用,运行时抱怨我的类型需要进行检测。我很好奇我错过了什么。

      我注意到自动生成的moles代码声明了必要的MoledAssembly属性。但在我的测试中,测试项目似乎必须声明这个属性;它不能由引用的程序集声明到项目。但是,在使用自动生成的程序集的情况下,它将属性可以声明为“outside”。这是我的假设,我可以看到拆卸自动生成的痣dll;我找不到任何其他差异。但是,正如我试图解释的那样,从反汇编的自动生成的moles dll复制所有代码(和属性)并构建我自己引用的程序集在运行时失败,说我没有标记所需的组装测试要进行检测(即用MoledAssembly标记) - 它只是在我引用的asssembly中。

      - 更新

      此时(可能是由于我对我的代码缺失的误解)我觉得我们需要非常具体地了解哪些程序集具有什么。假设我们有4个dll:

      1. Test.dll:mstest项目。未声明MoledAssembly
      2. Moles.dll:在项目中使用*.moles文件时创建的自动生成的dll。引用第4个dll,(参见#4)Sealed。声明[assembly: MoledAssembly("Sealed")]。请注意,我正在尝试在没有此dll的情况下完成手动鼹鼠注射 - 它只是一个概念性参考或用于我们的讨论或故障排除。
      3. MyMoles.dll:我自动生成的Moles.dll
      4. 的源代码编译版本
      5. Sealed.dll:包含待测代码。
      6. 在答案/评论/问题中 - 让我们根据此列表参考每个部分。

1 个答案:

答案 0 :(得分:4)

使用未自动生成的moled程序集时,必须使用assembly属性。 Moles Tools for Visual Studio 会自动提醒编译器存在生成的程序集。

通过Visual Studio添加Moles装配时,在构建项目之前不会生成mole装配。此外,不可能为尚不存在的程序集包含程序集属性。这样做会导致编译器失败。因此,Moles还必须动态地向编译器命令行添加命令,生成moled程序集,然后从项目中正确引用它们。

使用手动生成的moled程序集时,必须包含一个程序集属性,因为Moles工具由于程序集不是自动生成而不知道它的存在。程序员必须为Moles做好工作。

如果你想到目前为止,你可以在编译器参与之前使用代码生成。 PERL可以根据需要轻松注入必要的装配属性。当编译器收到代码时,它已经注入了属性。

支持我的答案的实验:

我能够重现你的问题。我还能够通过在 using 语句块下添加一个程序集属性来解决问题。我采取了以下步骤来构建我的示例应用程序:

  1. 创建了一个名为ClassLibrary2的.NET 4.0 C#类库项目。
  2. 在Class1中创建了以下方法:

    public string TestString(){return“原始值。”; }

  3. 创建一个测试项目(TestProject1),方法是右键单击TestString方法声明,然后选择创建单元测试... (懒惰,我知道。)

  4. 从Class1Test.cs中删除了额外的废话,留下了TestStringTest()。
  5. 为mscorlib添加了一个moles程序集。 (另一个懒惰的捷径,以及一个不必要的步骤,回想起来。我在这里注意到,因为这是我所做的。)
  6. 为ClassLibrary2添加了一个moles程序集。
  7. 使用默认任意CPU 配置文件编译的解决方案。
  8. 使用Redgate(对不起,@ payo)反编译ClassLibrary2.Moles
  9. 添加了一个名为MoleClassLibrary的新类库项目。
  10. 将反编译的MClass1和SClass1代码复制到MoleClassLibrary。
  11. 从TestProject1中删除了Class1.moles文件和程序集。
  12. 从TestProject1中删除了(不必要的)mscorlib.moles文件和程序集。
  13. 添加了对TestProject1的MoleClassLibrary引用。
  14. 更新了Class1Test.cs中的 using 语句。
  15. 构建解决方案。
  16. 使用 Visual Studio 2010 测试视图窗口执行TestStringTest()
  17. 测试失败,产生细节:
  18.   

    测试方法   TestProject1.Class1Test.TestStringTest   抛出异常:   Microsoft.Moles.Framework.Moles.MoleNotInstrumentedException:    System.String   ClassLibrary1.Class1.TestString()是   未检测解决此问题   问题,添加以下属性   测试项目:

         

    使用Microsoft.Moles.Framework;   [部件:   MoledAssembly(typeof运算(ClassLibrary1.Class1))]

    我将推荐的程序集属性添加到文件中。执行此操作后,测试方法成功运行。我怀疑编译器会自动引用生成的moled程序集,从而无需使用assembly属性。我尝试将MoleClassLibrary二进制文件复制到MolesAssemblies目录并创建一个MoleClassLibrary.moles文件,以测试该理论。仅当我包含assembly属性时才通过测试。这个结果对我的假设没有定论。

    这是Class1Test.cs的代码:

    using ClassLibrary1;
    using Microsoft.Moles.Framework;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using MoleClassLibrary;
    [assembly: MoledAssembly(typeof(ClassLibrary1.Class1))]
    
    namespace TestProject1
    {
        [TestClass()]
        public class Class1Test
        {
            [TestMethod()]
            [HostType("Moles")]
            public void TestStringTest()
            {
                var target = new Class1();
                var expected = "Mole value.";
                string actual;
                MClass1.AllInstances.TestString = value => expected;
                actual = target.TestString();
                Assert.AreEqual(expected, actual);
            }
        }
    }