Использование зависимости как конкретной реализации, так и макета в одной и той же TestFixture - PullRequest
1 голос
/ 13 октября 2019

У меня есть класс TestFixture, который выполняет некоторый код в моем текущем проекте. Большую часть времени я передаю фактическую, конкретную реализацию некоторых зависимостей в SUT. Однако я натолкнулся на случай, когда использование реальной вещи было бы нежелательным. Поскольку я использую пользовательский AutoDataAttribute для создания SUT, похоже, что теперь я потерял возможность заменять зависимость, которую я хочу, на макет, если только я не создаю все детали вручную.

SUT получает все свои зависимости с помощью инжектора конструктора:

public class MyService {
  private readonly IDependency dependency;

  public MyService(IDependency dependency, ...) {
    ...
    this.dependency = dependency ?? throw new ArgumentNullException();
    ...
  }
}

Вот как выглядит мой тестовый класс:

[TestFixture]
public class MyServiceTest {
  [Test, CustomAutoMock]
  public void TestCase1(int id, MyService sut) {
    ...
    sut.Dependency.Configure( ... );
    ...
    sut.DoSomethingWith(id);
    ...
    }

  [Test, CustomAutoMock]
  public void TestCase2(string searchString, MyService sut) {
    ...
    sut.Dependency.Configure( ... );
    ...
    sut.FindSomethingMatching(searchString);
    ...
    }

  ...

  [Test, CustomAutoMock]
  public void TestCaseN([Frozen] Mock<IDependency> mockDependency, MyService sut) {
    ...
    mockDependency.SetUp(o => o.DoSomething()).Throws<InvalidOperationException>();
    ...
    sut.Exercise();
    ...
    }
}

И это CustomAutoMockAttribute:

class CustomAutoMockAttribute : AutoDataAttribute {
  public CustomAutoMockAttribute() : base(InitializeCustomFixture) { }

  public static Fixture InitializeCustomFixture() {
    var fixture = new Fixture();

    fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true });

    ...

    fixture.Register<IDependency>(() => fixture.Create<ConcreteDependency>());

    ...

    return fixture;
  }
}

На самом деле MyService конструктор принимает 18 параметров! (Не смотри на меня так, это устаревший код, который был передан мне ?) Это одна из главных причин, почему AutoFixture так здорово сэкономил время, пытаясь получить этоКод контролируется побитно.

В MyServiceTest.TestCaseN я ожидал, что SUT получит смоделированную зависимость, но, несмотря ни на что, он всегда получает экземпляр ConcreteDependency.

Isесть ли способ настроить AutoFixture для подачи mockDependency в SUT без , когда мне придется создавать все вручную?

Ответы [ 2 ]

1 голос
/ 19 октября 2019

Хорошо, это то, что я в итоге сделал, и даже если это не очень красиво, это работает:

[TestFixture]
public class MyServiceTest {

  //...

  [Test, CustomAutoMock]
  public void TestCaseN(Fixture fixture, Mock<IDependency> mockDependency) {
    //...

    mockDependency
        .SetUp(o => o.DoSomething())
        .Throws<InvalidOperationException>();

    fixture.Inject(mockDependency.Object);
    var sut = fixture.Create<MyService>();

    //...

    sut.Exercise();

    //...

  }
}

Я знаю, что 18 зависимостей звучат безумно. Я чувствую боль за это, но по крайней мере с этим я могу постепенно начать тестировать эту кодовую базу, что, я надеюсь, позже позволит мне немного изменить ее.

1 голос
/ 15 октября 2019

Я думаю, что, возможно, вы не пытаетесь решить нужную проблему.

Убедитесь, что ваши 18 введенных зависимостей являются услугами, от которых на самом деле зависит.

Может бытьВы можете отвлечь их за одну услугу, которая будет сосредоточена на конкретной ответственности.

Абстрагирование от данной проблемы - отличный способ убедиться, что у вас нет гигантских конструкторов. И это должно быть выполнимо для рефакторинга, чтобы уменьшить количество зависимостей, даже от унаследованного кода. (Если в него уже введены зависимости, по крайней мере это не , что ужасно для унаследованного кода: P

С другой стороны, всегда хорошо автоматизировать шаблонный код размещения.

В свое время я начал писать плагин Roslyn для генерации введенных макетов. Я не знаю, каково текущее состояние дел с Visual Studio 2019, но, возможно, это может помочь.

https://github.com/salfab/moqlyn/tree/develop

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...