【问题标题】:How to force method to use a mock?如何强制方法使用模拟?
【发布时间】:2015-02-15 05:01:30
【问题描述】:

我的应用程序由各种具体的 Job 类组成(都继承自抽象 Job 类)。在他们的 Run() 方法中,他们通常调用外部服务。 我想测试我的工作课程并模拟服务结果。

这是典型的具体 Run() 方法的外观:

    InstallWpJobResult result = new InstallWpJobResult();
    WpManager wpManager = new WpManager();
    if (!WpManager.InstallWp(Domain, SiteTitle, WpUsername, WpPassword, WpEmail))
        result.Error = "Error installing WordPress";
    return result;

我希望 WpManager.InstallWp 返回 true(在模拟版本中)。 我知道如何模拟对象和方法,但如何让我的工作使用模拟版本? (现在它在方法本身内创建一个实例)。

顺便说一句,我正在使用 Moq 框架进行模拟。

【问题讨论】:

    标签: c# unit-testing mocking moq


    【解决方案1】:

    几个选项:

    1. 定义一个工厂服务 IWpManagerFactory 注入到您的作业类中,并使用一种方法来构造您的模拟 WpManager。
    2. 在您的作业中定义一个虚拟方法 BuildWpManager 并在您的测试中覆盖该方法以注入您的模拟。

    工厂服务方法的快速示例:

    public interface IWpManagerFactory
    {
        WpManager BuildWpManager();
    }
    
    public sealed class Tests
    {
        public void Test()
        {
            var manager = new Mock<WpManager>();
            //Set up mock manager here...
    
            var factory = new Mock<IWpManagerFactory>();
            factory.Setup(f => f.BuildWpManager()).Returns(manager.Object);
    
            //Inject factory to class under test and execute the method under test...
        }
    }
    

    这当然假设您的 WpManager 具有可以模拟的虚拟方法。如果没有,您还需要提取 IWpManager 接口,然后模拟它。

    【讨论】:

    • 我明白了。如果要求不高,您是否介意向我展示一个像 IWpManagerFactory 这样的工厂的快速示例?
    • 我明白了。非常感谢,有道理:)
    【解决方案2】:

    在消费者类中实例化具体类违反了 SOLID 原则之一(“D”或“依赖注入”)。原因之一是您遇到的原因:可测试性

    我建议您让WpManagerIInstallWpJobResult 的实例(注意它是一个接口)作为其构造的一部分,而不是实例化一个。这样,您可以轻松更改给定不同 IInstallWpJobResult 实现的类的行为,例如传入具有预定义行为的 Mock&lt;IInstallWpJobResult&gt;,以便于测试。

    一旦您开始使用依赖注入框架在运行时解决所有这些依赖项,这也会派上用场,因为它们通常会查看构造函数的参数以了解要注入的依赖项。

    【讨论】:

      猜你喜欢
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多