c# - 微软痣,动态仪器

标签 c# .net moles

痣有两种用途:

手动

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

动态

  1. 添加一个{项目名称}.moles 文件:将程序集指定为mole。例如 <Moles xmlns="http://schemas.microsoft.com/moles/2010/"> <Assembly Name="Samples.Moles"/> </Moles>
  2. 构建并包含对 MolesAssemblies/{project_name}.Moles.dll 的引用
  3. 使用 M{class_name} 自动生成的鼹鼠类。

我注意到使用动态程序集不需要测试项目声明“moled 程序集”属性。这减少了开销,开发人员只需要用 moles 的宿主类型装饰每个测试方法;但进一步的测试不需要跟踪要检测的类型。

查看 molesassemblies 中自动生成的代码(使用反汇编程序),很容易找到所需的检测属性。但是,尝试编写我自己的“鼹鼠程序集”(基本上替换自动生成的程序集)不起作用,并且运行时提示我的类型需要检测。我很好奇我错过了什么。

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

-- 更新

在这一点上(可能是由于我对我的代码缺少什么的误解)我觉得我们需要非常具体地说明什么程序集有什么。假设我们有 4 个 dll:

  1. Test.dll:mstest 项目。不申报MoledAssembly .
  2. Moles.dll:使用 *.moles 时自动生成的 dll文件在你的项目中。引用第 4 个 dll,(参见 #4)Sealed .声明 [assembly: MoledAssembly("Sealed")] .请注意,我正在尝试在没有此 dll 的情况下完成手动摩尔注入(inject) - 它只是一个概念引用或用于我们的讨论或故障排除。
  3. MyMoles.dll:我的自动生成的源代码编译版本 Moles.dll .
  4. Sealed.dll:包含被测代码。

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

最佳答案

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

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

当使用手动生成的模制程序集时,有必要包含一个程序集属性,因为由于程序集不是自动生成的,所以 Moles 工具不知道它的存在。程序员必须为 Moles 完成这项工作。

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

支持我的答案的实验:

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

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

    public string TestString() { 返回“原始值”。 }

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

  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 测试 View 窗口执行了 TestStringTest()。
  17. 测试失败,生成详细信息:

Test method TestProject1.Class1Test.TestStringTest threw exception: Microsoft.Moles.Framework.Moles.MoleNotInstrumentedException: The System.String ClassLibrary1.Class1.TestString() was not instrumented To resolve this issue, add the following attribute in the test project:

using Microsoft.Moles.Framework; [assembly: MoledAssembly(typeof(ClassLibrary1.Class1))]

我在文件中添加了推荐的程序集属性。这样做之后,测试方法就成功运行了。我怀疑编译器会自动引用生成的模制程序集,从而不再需要 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);
        }
    }
}

关于c# - 微软痣,动态仪器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6272217/

相关文章:

c# - 如何在 C# 中将文本与列表框中的 ITEMS 进行比较

c# - C#中的类型转换不起作用

c# - MVC5申请表导致提交时有多个post请求

c# - 根据另一个列表的内容对列表进行排序

asp.net - 在 .NET 6 中创建和使用类型化 http 客户端和 DI 时,我是否应该明确使用 httpClientFactory 类作为建议?

moles - Microsoft Moles 不会为具有过时成员的类型生成 Stub 或 Mole

c# - "Base class could not be loaded"- 没有明确的原因

c# - 获取源文件、方法和异常行

visual-studio-2012 - Visual Studio 2012 Fakes 不会为具有 Stream 返回类型的方法的接口(interface)生成 stub

.net - 在 System.Reflection 中使用 Moles