【问题标题】:Intercept Method/Property call in c#在c#中拦截方法/属性调用
【发布时间】:2015-04-29 02:16:06
【问题描述】:

在下面的代码中,我有一个类 Foo,它被我的 main 方法调用(没有接口)。该属性没有支持字段或设置器,而是调用私有方法。 Foo不能变,foo的用法也不能改成IFoo接口。

- 如何更改 foo.FooValue 的值?

- System.Reflection、System.Reflection.Emit、.NET 标准库等(不安全代码等)中是否有任何我可以包含在单元测试中以更改返回值的内容?

如果有什么东西肯定是“邪恶”的,我很感激,但我对“邪恶”的答案很感兴趣。

public class Program
{   
    public static void Main(){

        Foo foo = new Foo();
        int bar = foo.FooValue;
    }
}

public class Foo{

    public int FooValue
    {
        get
        {
            return this.FooMethod();
        }
    }

    private int FooMethod
    {
         return 0;
    }
}

相关问题:

How to set value of property where there is no setter - Related but unanswered - 也许答案是“不”,但我不相信最佳答案只是指出您无法通过更改(不存在的)支持字段来实现这一点。

Intercept call to property get method in C# - 有趣。不确定这是否是我的答案,如果是,不确定如何在单元测试中使用它。

编辑:好的。我将重新编写我的代码以使其更具可测试性。但是,出于兴趣,有没有人成功破解了这种情况?

【问题讨论】:

  • 您拥有Foo 类吗?您将其硬编码为返回 0。添加一个属性或字段,然后让它返回该属性并添加一个 setter。
  • 所以你的兴趣只是为了单元测试?你本质上是想通过改变Foo 的行为来“模拟”它吗?
  • @mason 我不拥有 Foo 类。我宁愿不重构,如果我要重构,我会通过使用 at 作为 IFoo 将 Foo 与我的代码分离。
  • @Dstanley 基本上,是的。我的三个步骤是:我可以模拟它(否),我可以反映它(否),让我们看看实现。
  • 您要测试FooValue 的值还是依赖 FooValue 的其他值?

标签: c# unit-testing reflection


【解决方案1】:

您可以为 Foo 创建一个可以模拟的代理:

public class FooProxy : IFoo
{
    private Foo _Foo;
    public FooProxy(Foo foo)
    {
        _Foo = foo;
    }
    public int FooValue
    {
        get {return _Foo.FooValue();
    }
}

public interface IFoo
{
    public int FooValue {get;}
}

然后您可以使用 DI 来“注入”IFoo 并使您的代码更具可测试性。

【讨论】:

  • 感谢您的回答。我知道如果我的代码使用接口,它会更容易测试。它通常不适用于 dto(foo 是一个 dto,有人对它的实现有点热心)。如果我这样做了,我可能只会使用 Moq 而不是代理。所以你对我的问题的回答是:“你的代码是不可测试的,在重构之外没有任何技巧来模拟 Foo”?
  • @NathanCooper - 我喜欢你旋转答案的方式:) - .Net 中没有轻量级的东西可以处理拦截对非虚拟/非接口方法的调用。某种形式的 IL 重写是最高的抽象层,您可以在其中使用调试接口或自定义 JIT/运行时来实现这一点……
  • @Nathan 您的程序与Foo 紧密耦合-如果您需要使用Foo 以外的其他方法测试您的方法,正确的方法是打破紧密耦合。可能存在低级方法(IL 重写等),但它们只是绕过了真正的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 2021-09-16
  • 2014-10-11
相关资源
最近更新 更多