用Moq(C#)监视对象

用Moq(C#)监视对象,c#,moq,spy,C#,Moq,Spy,我正在构建一个.NET核心应用程序,我想使用Moq监视一个实例化的对象,但我还没有找到一种方法 基本上,我需要的是所谓的间谍活动 我发现我可以使用以下方法调用类Foo的基类方法: var mock = new Mock<Foo>(); mock.CallBase = true; Moq不支持现有对象。但是,它确实接受参数来调用构造函数。当我们使用类似于decorator模式的变通方法时,这可能就是解决方案 请注意,使用(现有)实例时有一个警告:使用模拟实例(carMock.Ob

我正在构建一个.NET核心应用程序,我想使用Moq监视一个实例化的对象,但我还没有找到一种方法

基本上,我需要的是所谓的间谍活动

我发现我可以使用以下方法调用类
Foo
的基类方法:

 var mock = new Mock<Foo>();
 mock.CallBase = true;

Moq不支持现有对象。但是,它确实接受参数来调用构造函数。当我们使用类似于decorator模式的变通方法时,这可能就是解决方案

请注意,使用(现有)实例时有一个警告:使用模拟实例(
carMock.Object
)的类使用配置的设置。但是,被测试的类本身(
actualCar
)不知道它正在被修饰,因此不会如下面的示例所示

public class Car : ICar
{
    public virtual string Manufacturer { get; set; }
    public virtual string Model { get; set;}
    public virtual string Name => $"{Manufacturer} {Model}";
}

public class CarTestHelper : ICar
{
    private readonly ICar _innerCar;

    public CarTestHelper(ICar car)
    {
        _innerCar = car;
    }

    // These properties use the existing instance passed in the constructor
    public string Manufacturer { get => _innerCar.Manufacturer; set => _innerCar.Manufacturer = value; }
    public virtual string Model { get => _innerCar.Model; set => _innerCar.Model = value; } // Virtual property can be mocked using Moq
    public string Name => _innerCar.Name; // Does NOT use mocked 'Model'.
}    

[TestFixture]
public class CarTests
{
    [Test]
    public void NameIsManufacturerWithModel()
    {
        var actualCar = new Car
        {
            Manufacturer = "Nissan",
            Model = "100NX"
        };

        var carMock = new Mock<CarTestHelper>(actualCar)  // Pass the decorated car as constructor parameter
        {
            CallBase = true
        };

        carMock.SetupGet(c => c.Model).Returns("200SX");

        Assert.AreEqual("Nissan 200SX", carMock.Object.Name);  // Will fail as the car will not used the mocked value.
    }
}
公共级轿车:ICar
{
公共虚拟字符串制造商{get;set;}
公共虚拟字符串模型{get;set;}
公共虚拟字符串名称=>$“{Manufacturer}{Model}”;
}
公共类卡特尔管理员:ICar
{
私人只读ICar\u innerCar;
公共车手(ICar汽车)
{
_车内=车内;
}
//这些属性使用构造函数中传递的现有实例
公共字符串制造商{get=>\u innerCar.Manufacturer;set=>\u innerCar.Manufacturer=value;}
公共虚拟字符串模型{get=>\u innerCar.Model;set=>\u innerCar.Model=value;}//可以使用Moq模拟虚拟属性
公共字符串名称=>\u innerCar.Name;//不使用模拟的“Model”。
}    
[测试夹具]
公共阶级卡特尔
{
[测试]
public void nameismanufacturewhithmodel()
{
var实际值=新车
{
制造商=“日产”,
Model=“100NX”
};
var carMock=new Mock(actualCar)//将装饰过的汽车作为构造函数参数传递
{
CallBase=true
};
SetupGet(c=>c.Model).Returns(“200SX”);
Assert.AreEqual(“Nissan 200SX”,carMock.Object.Name);//将失败,因为汽车不会使用模拟值。
}
}
VisualStudio提供了一个很好的快速修复方法,可以在继承
ICar
并将其作为构造函数参数时自动实现装饰器模式

public class Car : ICar
{
    public virtual string Manufacturer { get; set; }
    public virtual string Model { get; set;}
    public virtual string Name => $"{Manufacturer} {Model}";
}

public class CarTestHelper : ICar
{
    private readonly ICar _innerCar;

    public CarTestHelper(ICar car)
    {
        _innerCar = car;
    }

    // These properties use the existing instance passed in the constructor
    public string Manufacturer { get => _innerCar.Manufacturer; set => _innerCar.Manufacturer = value; }
    public virtual string Model { get => _innerCar.Model; set => _innerCar.Model = value; } // Virtual property can be mocked using Moq
    public string Name => _innerCar.Name; // Does NOT use mocked 'Model'.
}    

[TestFixture]
public class CarTests
{
    [Test]
    public void NameIsManufacturerWithModel()
    {
        var actualCar = new Car
        {
            Manufacturer = "Nissan",
            Model = "100NX"
        };

        var carMock = new Mock<CarTestHelper>(actualCar)  // Pass the decorated car as constructor parameter
        {
            CallBase = true
        };

        carMock.SetupGet(c => c.Model).Returns("200SX");

        Assert.AreEqual("Nissan 200SX", carMock.Object.Name);  // Will fail as the car will not used the mocked value.
    }
}