我可以模拟无法实例化的对象吗?

Can I mock object which is impossible to instantiate?

我在我的 C# 中使用了一些 COM 库,它绑定到特定的硬件,没有它就无法工作。在 development/testing 计算机上我没有那个硬件。使用库的方法如下所示:

using HWSysManagerLib;
bool ProcessBias(HWSysManager systemManager, string hwPath)
{
    int handle = systemManager.OpenConfiguration(hwPath);
    ...
    // some magic goes here
    // return result
}

问题是,我可以为测试方法模拟 HWSysManager 吗?如何模拟? HWSysManager中只有很少的方法,模拟它们的功能进行测试不会有问题。如果可能的话,一个小例子会很好地说明如何模拟它。

我想你应该为你的模拟案例创建 HWSysManager(或其他名称)class,在其中添加一些想要的方法,然后模拟它们。例如:

    class HWSysManager
    {
        public virtual int ExampleReturnIntMethod(int a)
        {
            var someInt = 0;
            return someInt;
        }

然后设置:

    public void TestMethod()
    {
        Mock<HWSysManager> hwSysManager = new Mock<HWSysManager>();
        hwSysManager.Setup(x => x.ExampleReturnInMethod(It.IsAny<int> ())).Returns(10); //if parameter is any of int, return 10 in this case
    }

然后使用你的 Mocked 对象只需使用 'object' 属性:

 var hwSysInstance = hwSysManager.Object;
 var result = hwSysInstance.ExampleReturnInMethod(2); //result will be 10 in this case - as we have mocked

如果以上情况,您的 methods/properties 必须是虚拟的。

您也可以使用接口,在您的情况下:

    public interface HwsysManager
    {
        int OpenConfiguration(string hwPath);
    }

     public void TestMethod()
    {
      Mock<HwsysManager> hwsysManager = new Mock<HwsysManager>();

      hwsysManager.Setup(x => x.OpenConfiguration(It.IsAny<string>())).Returns(10);
    }

这里描述了这个 Mock 库的所有特性: https://github.com/Moq/moq4/wiki/Quickstart

您可以在此处使用适配器模式。

创建一个名为 IHWSysManager

的接口
public interface IHWSysManager
{
    int OpenConfiguration(string hwPath);
}

真正的实现class只是将工作委托给库:

public class HWSysManagerImpl : IHWSysManager
{
    private HWSysManager _hwSysManager; //Initialize from constructor

    public int OpenConfiguration(string hwPath)
    {
        return _hwSysManager.openConfiguration(hwPath);
    }
}

像这样在代码中使用接口:

bool ProcessBias(IHWSysManager systemManager, string hwPath)
{
    int handle = systemManager.OpenConfiguration(hwPath);
    ...
    // some magic goes here
    // return result
}

现在您可以使用模拟框架模拟您的 IHWSysManager 界面,或者您可以自己创建一个存根 class。

您可以使用 Typemock Isolator 伪造 HWSysManager。

对于您的示例,您可以执行以下操作:

var fakeManager = Isolate.Fake.Instance<HWSysManager>();

Isolate.WhenCalled(() => fakeManager.OpenConfiguration("")).WillReturn(0);

然后,您可以将这个伪造的经理作为参数传递给 ProcessBias(IHWSysManager systemManager, string hwPath)

正如您所说,您可以从 IHWSysManager 中模拟一些方法。因此,我的建议是使用 DoInstead():

设置该管理器方法的行为
Isolate.WhenCalled(() => fakeManager.OpenConfiguration("")).DoInstead(
    context =>
    {
        //Your simulation
    });

您可以查看here了解更多信息。我想,它对你真的很有用。