Шпионить за объектом с помощью Moq (C#)

Я создаю приложение .NET Core и хочу следить за созданным объектом с помощью Moq, но я не нашел способа сделать это.

По сути, мне нужно то, что описано здесь как шпионаж.

Я обнаружил, что могу вызывать методы базового класса класса Foo следующим образом:

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

Моя проблема в том, что Moq создаст новый экземпляр Foo, а мне нужно использовать уже созданный экземпляр объекта и имитировать только один метод реального объекта при вызове реальных функций объекта.

Вот структура объекта, за которым я хочу следить.

    public class Foo:Boo
    {
       Foo(Propeties props):base(props){}

       public Baz MockMe(){...}

       public Daz DoNotMockMe(){ 
           return DoSomethingWith(Properties);
        }
    }

person orestis    schedule 28.08.2019    source источник


Ответы (1)


Moq не поддерживает существующие объекты. Однако он принимает параметры для вызова конструкторов. Это может быть решением, когда мы используем обходной путь, такой как шаблон декоратора.

Обратите внимание, что при использовании (существующих) экземпляров существует предостережение: классы, использующие ваш имитированный экземпляр (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.
    }
}

В Visual Studio есть хорошее быстрое исправление для автоматической реализации шаблона декоратора, когда вы наследуете от ICar и используете его в качестве параметра конструктора.

person Myrtle    schedule 28.08.2019