Внедрение зависимостей с Moq и AutoMoq (AutoFixture) с xUnit - PullRequest
2 голосов
/ 12 апреля 2019

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

public class SomeController
{
    private ISomeInterface _i;
    private MyConfig _c;

    public SomeController(ISomeInterface i, MyConfigContext cxt) // Where cxt is Type of DbContext
    {
        _i = i;
        _c = cxt.Configs.FirstOrDefault();
    }

    public OkResult PostModel(SomeModel c)
    {
        // Do things
        return Ok();
    }
}

И в моих тестах с использованием xUnit, Moq и AutoFixture я пытаюсь избежать необходимости вручную создавать зависимости B и C:

public class SomeControllerTests
{
    private MyDbContext _cxt;
    private Fixture _fixture;

    public SomeControllerTests()
    {
        _cxt = GetCxt() // GetCxt() just returns a context instance, nothing special
       _fixture = new Fixture();
       _fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true });
       _fixture.Customizations.Add(
          new TypeRelay(
              typeof(ISomeInterface),
              typeof(SomeConcreteClass)
          )
       );
    }

    [Fact, AutoData]
    public void PostStatus_ReturnsOk_GivenValidRequest()
    {
        SomeController c = _fixture.Create<SomeController>();
        SomeModel m = _fixture.Create<SomeModel>();
        var result = c.PostModel(m);

        Asset.IsType<OkResult>(result);
    }
}  

С учетом вышесказанного я получаю NotImplementedException, когда я запускаю тесты, и они не сообщают мне, что именно не реализуется, поэтому у меня нет возможности узнать, в чем проблема.Я должен что-то упустить в документах.Я хочу использовать AutoFixture, чтобы сделать мои тесты более долговечными, но пока пытаться его использовать было тяжело.Я действительно не хочу издеваться над моим приложением, просто чтобы запустить тест.В идеале я хотел бы использовать синтаксис, показанный в документах AutoFixture, где вы помещаете свои релевантные для теста экземпляры в параметры теста, и они созданы для вас, но мне не повезло с этим, как ...

[Theory, AutoData]
SomeTestMethod(SomeController c, SomeModel m)
{
    var result = c.PostModel(m);

    Assert.IsType<OkResult>(result);
}

Спасибо за чтение (:

1 Ответ

0 голосов
/ 18 апреля 2019

Я думаю, что здесь происходят две вещи.

Во-первых, я предполагаю, что ваш контроллер наследуется от ControllerBase. Кажется, что Autofixture не может создать ControllerContext, это можно решить, внедрив его экземпляр во время настройки.

_fixture.Inject(new ControllerContext());

Вторая часть относится к тесту с этой структурой

[Theory, AutoData]
SomeTestMethod(SomeController c, SomeModel m)

Вставленные типы (SomeController и SomeModel) будут созданы до вызова конструктора SomeControllerTests (). Это означает, что настройка прибора слишком поздняя. Чтобы обойти это, нужно создать собственный атрибут AutoDataAttribute и переместить туда настройку, например:

public class ControllerAutoDataAttribute : AutoDataAttribute
{
    public ControllerAutoDataAttribute() : base(() =>
    {
        var fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
        fixture.Customizations.Add(
           new TypeRelay(
               typeof(ISomeInterface),
               typeof(SomeConcreteClass)
           )
        );
        fixture.Inject(new ControllerContext());
        return fixture;
    }){ }
}

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

[Theory, ControllerAutoData]
SomeTestMethod(SomeController c, SomeModel m)
{
    var result = c.PostModel(m);

    Assert.IsType<OkResult>(result);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...