Как захватить установку значения свойства с помощью Mock (Moq) - PullRequest
1 голос
/ 05 апреля 2019

В моем тестовом проекте я хочу зафиксировать свойство, установленное SUT, для смоделированного объекта.Я перепробовал много вещей, но, похоже, ни одна из них не позволяет мне это запечатлеть.

Я привел короткий пример:

Проверенный интерфейс:

public interface ISomeInterface
{
    string SomeProperty { get; set; }
}

SUT:

public class SomeSystemUnderTest
{
    public void AssignSomeValueToThis(ISomeInterface obj)
    {
        obj.SomeProperty = Guid.NewGuid().ToString();
    }
}

Тест:

[TestClass]
public class SomeTests
{
    [TestMethod]
    public void TestSomeSystem()
    {
        // Arrange
        var someInterfaceMock = new Mock<ISomeInterface>();

        someInterfaceMock.SetupSet(m => m.SomeProperty = It.IsAny<string>()).Verifiable();

        // Act
        var sut = new SomeSystemUnderTest();
        sut.AssignSomeValueToThis(someInterfaceMock.Object);

        // Assert
        // HERE I WOULD LIKE TO READ WHAT VALUE WAS ASSIGNED
        string myVal = someInterfaceMock.Object.SomeProperty;
    }
}

Переменная "myVal" остается нулевой, и, изучив макет, мы можем увидеть, что свойство все еще равно нулю.Я действительно не ожидал, что это будет иметь какое-то значение, просто пытаясь.

Я попытался с помощью Setup, с обратным вызовом, я получаю ошибки компиляции.

В реальном проекте SUT должен преобразоватьсвойство поддельного объекта к чему-то зависимому от другого свойства объекта.Чтобы узнать, выполняет ли объект свою работу, мне нужно прочитать свойство.Обратите внимание, я не могу перепроектировать макеты интерфейсов, они сторонние.

Я пытался использовать VerifySet, но, похоже, он принимает только жестко запрограммированное значение.

Спасибо, Мишель

1 Ответ

1 голос
/ 05 апреля 2019

Существует разница между get и set, и у mock фактически нет внутреннего состояния, а есть только те настройки, которым он пытается соответствовать и вести себя должным образом.Вы можете имитировать реальные get и set функциональные возможности, используя обратный вызов.Примерно так:

//Arrange
string someProperty = null;
var mock = new Mock<ISomeInterface>();

mock.SetupSet(m => m.SomeProperty = It.IsAny<string>())
    .Callback<string>(p => someProperty = p)
    .Verifiable();

// use func instead of value to defer the resulution to the invocation moment
mock.SetupGet(m => m.SomeProperty).Returns(() => someProperty);

//Act
mock.Object.SomeProperty = "test";

//Assert
Assert.AreEqual("test", mock.Object.SomeProperty);

Другая возможность состоит в том, чтобы использовать Capture сам по себе, он фактически существует в moq

//Arrange
List<string> someProperty = new List<string>();
var mock = new Mock<ISomeInterface>();

mock.SetupSet(m => m.SomeProperty = Capture.In(someProperty))
    .Verifiable();

mock.SetupGet(m => m.SomeProperty).Returns(() => someProperty.Last());

//Act
mock.Object.SomeProperty = "test";

//Assert
Assert.AreEqual("test", mock.Object.SomeProperty);
...