微软摩尔,动态仪器

pay*_*ayo 6 .net c# moles

摩尔可以用两种方式使用:

手动

  1. 包括[assembly:MoledType(typeof(_type_to_instrument))]
  2. 指定[HostType("Moles")]
  3. 调用Microsoft.Moles.Framework.Moles.MoleRuntime.SetMole(Delegate _stub,object _receiver,MethodInfo method);

动态

  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. 使用M {class_name}自动生成的mole类.

我注意到使用动态程序集不需要测试项目声明'moled assemblies'属性.这减少了开销,开发人员只需要使用主机类型为每个测试方法装饰摩尔; 但进一步测试不需要跟踪要测量的类型.

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

我注意到自动生成的moles代码声明了必要的MoledAssembly属性.但在我的测试中,测试项目似乎必须声明这个属性; 它不能由引用的程序集声明到项目.但是,在自动生成程序集的情况下,它的APPEARS属性可以声明为"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. Sealed.dll:包含被测代码.

在答案/评论/问题中 - 让我们根据此列表引用每个部分.

Mik*_*ian 4

当使用非自动生成的模制装配体时,装配体属性是必需的。Visual Studio 的 Moles 工具会根据需要自动提醒编译器存在生成的程序集。

通过 Visual Studio 添加 Moles 程序集时,只有在构建项目后才会生成 Moles 程序集。此外,不可能包含尚不存在的程序集的程序集属性。这样做会导致编译器失败。因此,Moles 也有必要动态地将命令添加到编译器命令行中,以生成 moled 程序集,然后从项目中正确引用它们。

当使用手动生成的 moled 程序集时,必须包含程序集属性,因为 Moles 工具由于程序集不是自动生成的而无法意识到其存在。程序员必须为鼹鼠做这项工作。

如果您想走得更远,您可以在编译器参与之前使用代码生成。PERL 可以在需要时轻松注入必要的程序集属性。当编译器收到代码时,它已经注入了属性。

支持我答案的实验:

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

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

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

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

  4. 从 Class1Test.cs 中删除了多余的内容,留下了 TestStringTest()。
  5. 为 mscorlib 添加了 Moles 程序集。(回想起来,这是另一个懒惰的捷径,也是一个不必要的步骤。我在这里记下它,因为这是我所做的事情。)
  6. 为 ClassLibrary2 添加了 Moles 程序集。
  7. 使用默认的Any 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. 测试失败,产生详细信息:

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

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

我将推荐的程序集属性添加到文件中。这样做之后,测试方法运行成功。我怀疑编译器会自动引用生成的模制程序集,从而不再需要程序集属性。我尝试将 MoleClassLibrary 二进制文件复制到 MolesAssemblies 目录并创建 MoleClassLibrary.moles 文件,以测试该理论。仅当我包含程序集属性时测试才通过。这个结果对我的假设来说并不确定。

这是 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)