【问题标题】:How can I verify if a method is called inside another method如何验证一个方法是否在另一个方法中被调用
【发布时间】:2013-07-04 03:56:01
【问题描述】:

我试图找到一个例子,但没有成功,所以这就是我问这个问题的原因。

让我们从一些代码开始。这是我的代码:

class Dummy
{
    public void DoDummyThings1()
    {
        Console.WriteLine("Sorry, I'm dummy 1...");
    }

    public void DoDummyThings2()
    {
        Console.WriteLine("Sorry, I'm dummy 2...");
    }

    public void DoDummyThings3()
    {
        Console.WriteLine("Sorry, I'm dummy 3...");
    }
}

还有我的测试代码:

[TestClass]
public class UnitTest
{
    private Dummy dum = new Dummy();

    [TestInitialize()]
    public void SetUp()
    {
        MethodInfo mi = typeof (UnitTest).GetMethod("TestDummy");
        MethodBody mb = mi.GetMethodBody();
    }

    [TestMethod]
    public void TestDummy()
    {
        this.dum.DoDummyThings1();
        this.dum.DoDummyThings2();
        this.dum.DoDummyThings3();
    }
}

这就是我想要做的。我想在执行每个测试方法之前查看测试方法并检查是否会调用 Dummy 类的方法 DoDummyThings1、DoDummyThings2 和 DoDummyThings3。

这样做的目的是,根据调用的 DoDummyThingsX 方法,我想在代码深处的某处注入不同的实现,以在运行时修改某些类的行为(将接口的注入实现交换为另一个)。

谁能解释我如何正确地做到这一点(使用最新版本的 Cecil 或其他 C# 版本)? 有没有办法在不使用 .dll 文件的情况下做到这一点? (目前,这是我想出如何做到这一点的唯一方法,但是,我无法使用硬编码的字符串作为“MyDllName.dll”和“MyNamespace.MyClassName”)

我已经知道的其他 stackoverflow 线程:

谁能帮助我提供一个完整(但简单)的示例(如果可能的话)? 谢谢!

【问题讨论】:

    标签: c# reflection mstest system.reflection mono.cecil


    【解决方案1】:

    此答案演示了如何确定哪些测试执行 Dummy 方法但没有回答:

    在代码深处注入不同的实现,以在运行时修改某些类的行为

    反射不提供对您需要的单元测试方法的 IL 主体的精细访问;但是Cecil 提供了这个功能。以下 linq 返回内部调用 DoDummyThings1 的方法列表。 linq 可能更有效,但我想尽可能清楚。 where 子句是重要的部分。

    //syntax based on version 0.9.5.4 (http://nuget.org/packages/Mono.Cecil/0.9.5.4)
    using Mono.Cecil;  
    using Mono.Cecil.Cil;
    //...
    string assemblyPath = (@"path to your unit test assembly\MyTests.dll");
    AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(assemblyPath);
    
    List<MethodDefinition> testsThatCallDummyMethods =
           (from mod in asm.Modules
            from t in mod.Types
            from meth in t.Methods
            where meth.HasBody
            from instr in meth.Body.Instructions
            let op = instr.Operand as MethodDefinition
            where
                instr.OpCode == OpCodes.Callvirt &&
                op != null &&
                op.DeclaringType.FullName ==
                "Lib.Dummy" //namespace qualified type name
                && op.Name ==
                "DoDummyThings1" //method names...
            select meth)
            .ToList();
    

    使用ILDasm 反汇编测试程序集以找出操作码/操作数。 TestDummy 方法的相关部分类似于:

      //this.dum.DoDummyThings1();
      IL_0001:  ldarg.0
      IL_0002:  ldfld      class Lib.Dummy Lib.UnitTest::dum
      IL_0007:  callvirt   instance void Lib.Dummy::DoDummyThings1()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      • 1970-01-01
      相关资源
      最近更新 更多