如何强制方法使用模拟

本文关键字:模拟 方法 何强制 | 更新日期: 2023-09-27 18:34:32

我的应用程序由各种具体的作业类组成(都继承自抽象的作业类(。在他们的 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 框架进行模拟。

如何强制方法使用模拟

几个选项:

  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 接口,然后模拟它。

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

我建议你让WpManagerIInstallWpJobResult的一个实例(注意它是一个接口(作为其构造的一部分,而不是实例化一个。通过这种方式,您可以轻松地更改给定不同IInstallWpJobResult实现的类的行为,例如,传递具有预定义行为的Mock<IInstallWpJobResult>以便于测试。

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