【问题标题】:How to mock a method called inside another method?如何模拟在另一个方法中调用的方法?
【发布时间】:2014-06-24 10:10:42
【问题描述】:

我想用一个例子来解释我的问题。

Class A
{
    Fun1()
    {
        // some code
        B obj2 = new B();
        obj2.Fun2();
    }
}

Class B
{
    Fun2() 
    {
        // some code
    }
}

// Test Class for Class A
Class A_Test
{
    Fun1_Test()
    {
        A obj1 = new A();
        A.Fun1();
    }
}

我在这里调用Fun1,它调用fun2()。我想模拟对 fun2() 的调用。

我只需要在 Fun1() 中初始化 B 类对象,我不想使用构造函数。

可以模拟对 fun2() 的调用吗?

【问题讨论】:

  • 不要使用直接依赖使用依赖注入。如果你先阅读 SOLID 原则会更好。
  • 对于模拟 B 类,您必须将其模拟实现传递给 A 类。按您的方式,您不能这样做。这是使用接口而不是特定实现的原因之一。

标签: c# unit-testing moq


【解决方案1】:

你不能,因为Fun2 是在Fun1 内部创建的对象的实例方法

由于A依赖于B,如果要实现真正的隔离,则应将B注入A

您还应该“依赖于抽象”,正如依赖倒置原则所宣传的那样。使B 实现接口IB,并使A 依赖于IB。然后,您模拟接口 IB 并注入该模拟。

class A
{
    public Fun1(IB ib) { ib.Fun2(); }
}

interface IB
{
    Fun2();
}

class B : IB
{
    public Fun2() {}
}

// Test Class for Class A
Class A_Test
{
    Fun1_Test()
    {
        var bMock = new Mock<IB>();
        bMock.Setup(b => b.Fun2());

        A obj1 = new A();
        A.Fun1(bMock.Object);
    }
}

阅读:

  1. Dependency Inversion Principle
  2. Dependency Injection

【讨论】:

  • 如果在这个例子中使用接口会更好。
  • @loop 是的,我删除了 other 建议,因为它可能会鼓励读者选择最快的路径而不是正确的路径。
  • 感谢您的建议。但不幸的是,我不允许对那段代码进行更改,尽管我需要为它编写一个测试方法。还有其他方法可以测试 Fun1() 吗?
  • @dcastro 你能看看我的一个问题吗,stackoverflow.com/questions/24373600/… 我是 UnitTesting 的新手。
  • @Atul 对不起,不。代码有缺陷,AB 之间存在很强的依赖关系,这使得代码无法进行单元测试,并且将来很难维护。它必须改变。
【解决方案2】:

经典示例展示了如果您无法对特定组件进行单元测试,如何重构该组件!

这就是喜欢任何模拟框架强制您执行的操作 - 编写解耦代码。

在您的示例中,A 类与 B 的具体实现非常紧密地耦合。您可以使用(如大多数答案所建议的那样)依赖注入来解耦它。这样一来,您最终将依赖于 IB 抽象,而不是它的任何具体实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多