Автоматически возвращать значения фикстуры из имитирующих общих функций?

В моих тестах используются Moq и AutoFixture, и часто они очень подробны, потому что в них есть много имитационных вызовов Setup () для настройки имитаторов для возврата значений, созданных AutoFixture. Чтобы упростить чтение и поддержку тестов, я пытаюсь использовать AutoMoqCustomization с функцией ConfigureMembers, чтобы избежать ненужных вызовов Setup ().

В основном это работает так, как ожидалось, однако у меня есть несколько интерфейсов с универсальными функциями (в основном AutoMapper), которые AutoMoqCustomization, похоже, не обрабатывает. Вместо того, чтобы возвращать экземпляр типа из AutoFixture, я получаю фиктивный экземпляр.

Я могу добиться желаемого поведения, включив вызов Setup () для общей функции, но моей целью было удалить как можно больше этих вызовов Setup.

Я создал приведенный ниже пример, чтобы воспроизвести проблему (на практике я использую AutoFixture для внедрения экземпляра IMapper через конструктор другого объекта, и этот объект выполняет вызов интерфейса IMapper, но это не обязательно, чтобы увидеть проблемную поведение).

Я ожидаю, что вызов sut.Map<object>() будет работать как вызов sut.Map(), возвращая экземпляр object, замороженный в фикстуре. Вместо этого в переменной retB я вижу экземпляр ObjectProxy.

Включение закомментированной строки в пример, который устанавливает возвращаемое значение для Map<object>(), приведет к тому, что тест будет пройден, но я бы предпочел опустить этот вызов так же, как я могу опустить вызов Setup () для Map().

Предполагается ли, что общие функции настраиваются автоматически? Я неправильно его настраиваю?

using AutoFixture;
using AutoFixture.AutoMoq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace UnitTestProject1
{
    public interface IMapper
    {
        object Map();
        object Map<T>();
    }

    [TestClass]
    public class Tests
    {
        [TestMethod]
        public void Test()
        {
            var f = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
            var model = f.Freeze<object>();
            var sut = f.Create<IMapper>();

            //Mock.Get(sut).Setup(x => x.Map<object>()).ReturnsUsingFixture(f);

            var retA = sut.Map();
            var retB = sut.Map<object>();

            Assert.AreEqual(model, retA);
            Assert.AreEqual(model, retB);        }
    }
}


person DaveK    schedule 24.08.2020    source источник


Ответы (1)


Действительно, общие методы в настоящее время не поддерживаются настройкой AutoMoq в автофиксации из-за ограничений в том, как это написано, но есть проблема / PR, которая могла бы его интегрировать: https://github.com/AutoFixture/AutoFixture/issues/1139

Насколько я могу судить, он просто еще не объединен, потому что он потянет за собой более высокую версию зависимости Moq. Он использует относительно недавно введенное свойство Moq DefaultValueProvider, чтобы делегировать все обязанности «значения по умолчанию» AutoFixture вместо того, чтобы Moq рекурсивно вводил фиктивные объекты. Похоже, именно то, что вы хотите.

Из проблемы вот пример того, как бы выглядело использование, если бы вы вводили настройку, аналогичную той, которая запрос на перенос вводит:

var fixture = new Fixture();
fixture.Customize<string>(x => x.FromSeed(y => "asf"));
var mock = new Mock<IInterfaceWithGenericMethod>
{
    DefaultValueProvider = new AutoFixtureValueProvider(fixture)
};

Assert.Equal("asf", mock.Object.GenericMethod<string>());
person Jeff Dammeyer    schedule 24.08.2020
comment
Отлично, спасибо! Сейчас я просто добавлю вызовы Setup () и с нетерпением жду обновлений. - person DaveK; 25.08.2020