Как я могу использовать метод Moq SetReturnsDefault для классов? - PullRequest
0 голосов
/ 06 мая 2020

Примерно через час попыток заставить метод Moq SetReturnsDefault работать с моими тестами, я скопировал тест прямо из репозитория Moq версии 4:

    // I didn't copy this part:
    public interface IFoo
    {
        public int Value { get; set; }
    }

    // Just this part:
    [Fact]
    public void ReturnsDefaultValueOnProperty()
    {
        var mock = new Mock<IFoo>();
        mock.SetReturnsDefault(int.MinValue);

        Assert.Equal(int.MinValue, mock.Object.Value); 
        // Passes ✔
    }

Что работает. Однако, когда я заменяю интерфейс IFoo на класс Foo, он терпит неудачу:

    public class Foo
    {
        public int Value { get; set; }
    }

    [Fact]
    public void ReturnsDefaultValueOnProperty()
    {
        var mock = new Mock<Foo>();
        mock.SetReturnsDefault(int.MinValue);

        Assert.Equal(int.MinValue, mock.Object.Value); 
        // ❌ Assert.Equal() Failure Expected: -2147483648 Actual: 0
    }

Я предполагаю, что когда он использует конструктор по умолчанию для Foo, Value устанавливается на default(int), на который Moq должен посмотреть и решить, что ему не нужно использовать значение по умолчанию SetReturnsDefault? Большинство, если не все классы, которые я тестирую, выглядят примерно как Foo: как мне установить значения по умолчанию для свойств в Moq, не меняя сами классы?

В частности, я хотел бы установить строковые значения по умолчанию для всех свойств string и object в моих классах.

1 Ответ

0 голосов
/ 11 мая 2020

Вы не можете.

Как указал Нкози, Moq может работать только с переопределяемыми элементами (virtual или abstract). В итоге я создал экземпляры своих моделей для каждого теста, что я должен был сделать в первую очередь (я просто ленив). Если вы действительно хотите автоматически присваивать значения своим моделям без изменения их структуры, вы можете использовать отражение во вспомогательном методе, который сравнивает типы свойств класса для присвоения значений:

foreach (var property in foo.GetType().GetProperties()) 
{
    if (property.PropertyType == typeof(string)) {
        property.SetValue(foo, "default value");
    }
    // etc...
}

Само собой разумеется, , но если вы go этот маршрут, сделайте его максимально простым, чтобы избежать внесения ошибок в ваш тестовый код.

...