2017-01-29 5 views
1

Я пишу (NUnit) модульные тесты, предназначенные для компонента типа MyService. Пример:Почему AutoModject AutoMoqData не создает макет объектов?

public class MyService : IMyService 
{ 
    private readonly IMyRepo _myRepo; 

    public MyService (IMyRepo myRepo) 
    { 
     _myRepo = myRepo; 
    } 

    public MyService() 
    { 
     _myRepo = new MyRepo(); 
    } 
    ... 
} 

Я пытаюсь использовать AutoFixture как factory, который будет генерировать мой тест цели. Я также пытаюсь заставить его (AutoFixture) заполнить мою цель с помощью mock-зависимостей (используя Moq).

Вот моя попытка сделать это:

[Test, AutoMoqData] 
public void MyTest(MyService target) 
{ 
    ... 
} 

Атрибут [AutoMoqData] (на основе @ploeh's blog post) расширяет атрибут AutoFixture в [AutoData] с AutoMoqCustomization функции AutoFixture в:

public class AutoMoqDataAttribute : AutoDataAttribute 
{ 
    public AutoMoqDataAttribute() 
     : base(new Fixture() 
      .Customize(new AutoMoqCustomization())) 
    { 
    } 
} 

При запуске модульных тестов, основанных на выше, я хотел бы получить реальный экземпляр MyService с зависимостью Mock<IMyRepo> внутри него. Вместо этого я получаю конкретный пример MyRepo.

Кажется, что AutoMoqCustomization выбирает самый простой конструктор - тот, у которого нет аргументов. Как я могу настроить AutoMoqCustomization, чтобы игнорировать его и вместо этого создать экземпляр второго конструктора?

PS - Вот список соответствующих пакетов NuGet в использовании:
<package id="AutoFixture" version="3.50.2" targetFramework="net452" /> <package id="AutoFixture.AutoMoq" version="3.50.2" targetFramework="net452" /> <package id="AutoFixture.NUnit3" version="3.50.2" targetFramework="net452" /> <package id="Moq" version="4.5.29" targetFramework="net452" /> <package id="NUnit" version="3.5.0" targetFramework="net452" />

+1

Просьба перечислить ваши зависимости пакета NuGet. –

+1

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

+0

Спасибо @MarkSeemann. Просто попробовал минимальное воспроизведение в новом проекте, и теперь он работает. Скоро будет обновляться. – urig

ответ

1

Вы можете попробовать define a greedy constructor selection algorithm for AutoFixture, но на самом деле, лучшим решением является удаление конструктор без параметров:

public class MyService : IMyService 
{ 
    private readonly IMyRepo _myRepo; 

    public MyService (IMyRepo myRepo) 
    { 
     _myRepo = myRepo; 
    } 
} 

Наличие безпараметрического конструктора - это запах кода, называемый Bastard Injection. В большинстве случаев для этого нет веских оснований.

На мой взгляд, лучшим вариантом является применение принципа прослушивания GOOS. Когда тест становится трудным для записи, пришло время пересмотреть дизайн системного теста (SUT). AutoFixture имеет тенденцию усиливать этот эффект. Вот что здесь происходит.

+0

Большое спасибо за супер-быстрое решение. Действительно, пустой ctor - это запах кода: '[Устаревший (« Пожалуйста, не используйте этот ctor. Используется только для устаревания старых статических классов. », False)]'. Работая при расчистке: ' – urig