痣有两种用途:
手动
- 包括[程序集:MoledType(typeof(_type_to_instrument))]
- 指定 [HostType("Moles")]
- 调用 Microsoft.Moles.Framework.Moles.MoleRuntime.SetMole(Delegate _stub, object _receiver, MethodInfo 方法);
动态
- 添加一个{项目名称}.moles 文件:将程序集指定为mole。例如
<Moles xmlns="http://schemas.microsoft.com/moles/2010/"> <Assembly Name="Samples.Moles"/> </Moles>
- 构建并包含对 MolesAssemblies/{project_name}.Moles.dll 的引用
- 使用 M{class_name} 自动生成的鼹鼠类。
我注意到使用动态程序集不需要测试项目声明“moled 程序集”属性。这减少了开销,开发人员只需要用 moles 的宿主类型装饰每个测试方法;但进一步的测试不需要跟踪要检测的类型。
查看 molesassemblies 中自动生成的代码(使用反汇编程序),很容易找到所需的检测属性。但是,尝试编写我自己的“鼹鼠程序集”(基本上替换自动生成的程序集)不起作用,并且运行时提示我的类型需要检测。我很好奇我错过了什么。
我注意到自动生成的地鼠代码声明了必要的 MoledAssembly 属性。但是在我的测试中,测试项目好像要声明这个属性;它不能由项目的引用程序集声明。但是,在使用自动生成的程序集的情况下,似乎可以将属性 声明为“外部”。这是我的假设,基于我在反汇编自动生成的 moles dll 时所看到的;我找不到任何其他区别。然而,正如我试图解释的那样,从反汇编的自动生成的 moles dll 复制所有代码(和属性)并构建我自己的引用程序集在运行时失败,说我没有标记需要检测的待测程序集(即标有 MoledAssembly)- 它只是在我引用的组件中。
-- 更新
在这一点上(可能是由于我对我的代码缺少什么的误解)我觉得我们需要非常具体地说明什么程序集有什么。假设我们有 4 个 dll:
- Test.dll:mstest 项目。不申报
MoledAssembly
. - Moles.dll:使用
*.moles
时自动生成的 dll文件在你的项目中。引用第 4 个 dll,(参见 #4)Sealed
.声明[assembly: MoledAssembly("Sealed")]
.请注意,我正在尝试在没有此 dll 的情况下完成手动摩尔注入(inject) - 它只是一个概念引用或用于我们的讨论或故障排除。 - MyMoles.dll:我的自动生成的源代码编译版本
Moles.dll
. - Sealed.dll:包含被测代码。
在答案/评论/问题中 - 让我们根据此列表引用每个部分。
最佳答案
当使用非自动生成的模制程序集时,程序集属性是必需的。 Visual Studio 的 Moles 工具 会在必要时自动提醒编译器存在生成的程序集。
通过 Visual Studio 添加 Moles 程序集时,直到构建项目时才会生成 mole 程序集。此外,不可能为尚不存在的程序集包含程序集属性。这样做会导致编译器失败。因此,Moles 也有必要在编译器命令行中动态添加命令,生成 moled 程序集,然后从项目中正确引用它们。
当使用手动生成的模制程序集时,有必要包含一个程序集属性,因为由于程序集不是自动生成的,所以 Moles 工具不知道它的存在。程序员必须为 Moles 完成这项工作。
如果您想走得更远,您可以在编译器参与之前使用代码生成。 PERL 可以在需要的地方轻松地注入(inject)必要的程序集属性。当编译器收到代码时,它已经注入(inject)了属性。
支持我的答案的实验:
我能够重现您的问题。我还能够通过在 using 语句 block 下方添加一个程序集属性来解决该问题。我采取了以下步骤来构建我的示例应用程序:
- 创建了一个名为 ClassLibrary2 的 .NET 4.0 C# 类库项目。
在 Class1 中创建了以下方法:
public string TestString() { 返回“原始值”。 }
创建了一个测试项目 (TestProject1),方法是右键单击 TestString 方法声明,然后选择 Create Unit Tests...(懒惰,我知道。)
- 删除了 Class1Test.cs 中多余的废话,留下了 TestStringTest()。
- 为 mscorlib 添加了一个 moles 程序集。 (回想起来,这是另一个懒惰的捷径,也是一个不必要的步骤。我在这里记录下来,因为这是我做过的事情。)
- 为 ClassLibrary2 添加了一个 moles 程序集。
- 使用默认的 Any CPU 配置文件编译解决方案。
- 使用 Redgate(抱歉,@payo)反编译 ClassLibrary2.Moles
- 添加了一个名为 MoleClassLibrary 的新类库项目。
- 将反编译的 MClass1 和 SClass1 代码复制到 MoleClassLibrary。
- 从 TestProject1 中删除了 Class1.moles 文件和程序集。
- 从 TestProject1 中删除了(不必要的)mscorlib.moles 文件和程序集。
- 添加了对 TestProject1 的 MoleClassLibrary 引用。
- 更新了 Class1Test.cs 中的using语句。
- 构建解决方案。
- 使用 Visual Studio 2010 测试 View 窗口执行了 TestStringTest()。
- 测试失败,生成详细信息:
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/