是否可以使用 Moq 从实例中获取模拟实例?

ren*_*gbp 6 c# moq

假设我有这个接口和这个类:

public interface IScheduler
{
    void StopTimer();

    // some other methods
}

public class Scheduler : IScheduler
{
    private static readonly IScheduler scheduler = new Scheduler();

    private readonly Timer timer;

    public Scheduler()
    {
        refreshTimer = new Timer
        {
            Enabled = false,
            AutoReset = false
        };
    }

    public static IScheduler GetScheduler()
    {
        return scheduler;
    }

    public void StopTimer()
    {
        timer.Stop();
    }

    // some other methods
}
Run Code Online (Sandbox Code Playgroud)

所以我想知道是否可以从 GetScheduler 方法获得一个模拟实例。我试过这样的事情:

[TestMethod]
public void Execute_ButtonClicked_StopTimer()
{
    // arrange
    var mockScheduler = Mock.Get(Scheduler.GetScheduler());
    var command = GetCommandInstance();

    // act
    command.Execute();

    // assert
    mockScheduler.Verify(m => m.StopTimer());
}
Run Code Online (Sandbox Code Playgroud)

但没有用,它说“System.ArgumentException:对象实例不是由 Moq 创建的。”

请问有什么建议吗?

在命令类里面有这样的东西:

public void Execute()
{
    // some code
    Scheduler.GetScheduler().StopTimer();
}
Run Code Online (Sandbox Code Playgroud)

Ric*_*imo 5

我提出了一种不同的方法,可以避免这样做......

Scheduler 类正在实现单例模式来控制其构造。您需要能够抽象依赖于IScheduler它的构造方式的事物。所以其他东西应该有责任管理调度器的构造:它不应该自己做,因为构造不是那个类的责任(单一责任原则)。

对此的常用方法是使用四人组工厂方法模式服务定位器模式(例如 Microsoft 的 UnityContainer)。其中任何一个都可以指示将该类公开为单例,而使该类仅作为该类负责内容的实现。

依赖注入完成了拼图,因为当类注入它们的依赖项时,它们本身就从它们使用的事物的构造中抽象出来。所以一个需要 a 的类IScheduler会注入一个并使用它。

有了这些模式,执行问题中要求的操作的需求就消失了,并导致代码具有明确的关注点分离。

脚注:我知道这些模式的事情看起来令人生畏,而且似乎为此付出了很多努力,而且很难看到好处;但请相信我:试试这个(我的意思是尝试它,你不能只是三心二意的尝试,因为它是方法上的一个很大的变化)。我曾经像您发布的那样编写代码。我被建议看看这些模式。我有严重的怀疑,但我从未回头,现在我以这种方式编写所有代码。