Как я могу изменить приспособление, созданное моим пользовательским атрибутом данных теории для AutoFixture?

Я действительно ценю мощь AutoFixture в сочетании с теориями XUnit. Недавно я начал использовать инкапсуляцию настроек и предоставление их своим тесты через атрибут.

В некоторых случаях мне нужен одноразовый сценарий для запуска теста. Когда я использую AutoDomainDataAttribute, как описано выше, могу ли я запросить IFixture и ожидать получения того же экземпляра, созданного атрибутом?

В моем сценарии я использую MultipleCustomization по умолчанию для коллекций и т. д. Однако в этом случае я хочу, чтобы в конструктор моего SUT отправлялся только один элемент. Итак, я определил свой метод тестирования следующим образом:

[Theory, AutoDomainData]
public void SomeTest(IFixture fixture) {
  fixture.RepeatCount = 1;
  var sut = fixture.CreateAnonymous<Product>();
  ...
}

К сожалению, я получаю исключение при создании анонимного продукта. Другие тесты работают нормально, если я запрашиваю Product в качестве параметра метода с этими атрибутами. Это проблема только в данном конкретном случае, когда я надеюсь, что параметр приспособления — это тот же самый параметр, созданный моим атрибутом AutoDomainDataAttribute.

Конструктор продукта ожидает IEnumerable, который обычно заполняется тремя элементами из-за настроек, которые у меня есть на месте через AutoDomainData. В настоящее время моя DomainCustomization представляет собой CompositeCustomization, состоящую из MultipleCustomization и AutMoqCustomization, в указанном порядке.

Исключение: «InvalidCastException: невозможно преобразовать объект типа «Castle.Proxies.ObjectProxy» в тип «Product».


person ventaur    schedule 29.10.2012    source источник


Ответы (1)


Если вам нужен тот же экземпляр Fixture, что и активный в атрибуте, вы можете внедрить Fixture в себя в настройке, например так:

public class InjectFixtureIntoItself : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Inject(fixture);
    }
}

Просто не забудьте добавить это в свою CompositeCustomization перед AutoMoqCustomization, поскольку IFixture — это интерфейс, и если AutoMoqCustomization будет первым, вместо этого вы получите экземпляр Mock — AFAICT, это то, что в настоящее время происходит с динамическим прокси-сервером Castle. .


Однако, если вам действительно нужен экземпляр Fixture, почему бы просто не написать обычный императивный метод тестирования:

[Fact]
public void SomeTest()
{
    var fixture = new Fixture().Customize(new DomainCustomization());
    fixture.RepeatCount = 1;
    var sut = fixture.CreateAnonymous<Product>();
    // ...
}

Мне кажется, так намного проще... Я и сам иногда так делаю...


Тем не менее, мне интересно, не могли бы вы сформулировать свой API или тестовый пример по-другому, чтобы решить всю проблему. В последнее время мне очень редко приходится манипулировать свойством RepeatCount, поэтому мне интересно, зачем вам это?

Хотя, вероятно, это тема отдельного вопроса о переполнении стека...

person Mark Seemann    schedule 29.10.2012
comment
Спасибо, Марк. Я сразу же переключился на императивный подход к тестированию после публикации здесь. Хотя приятно знать альтернативу. Наконец, мой конкретный тест гарантирует, что последняя категория не может быть удалена из продукта (должна быть хотя бы одна). Это единственный раз, когда мне нужно было контролировать RepeatCount. Спасибо еще раз! - person ventaur; 30.10.2012
comment
Разве вы не могли сначала удалить Categories.Count() - 1 элементов как часть вашей тестовой установки, а затем проверить, что если остался только один, вы не сможете удалить последний? - person Mark Seemann; 30.10.2012
comment
Да, я так полагаю. Мы, программисты, иногда страдаем от чрезмерного усложнения вещей. :-) - person ventaur; 30.10.2012