Как подделать метод интерфейса динамически с FakeItEasy при тестировании контроллеров ASP.NET Core - PullRequest
0 голосов
/ 16 мая 2019

Написание тестов для контроллеров CRUD, которые следуют этому шаблону.

  1. Получить один или несколько параметров различных типов из параметров метода действия
  2. Вызвать некоторый метод IEntityService.GetEntity (параметры из шага 1)
  3. Если возвращается NULL, вернуть NotFound
  4. В противном случае вернуть найденный объект

Я неоднократно писал очень похожие тесты.

        [TestCase(true)]
        [TestCase(false)]
        public void GetsAccount(bool isExistingAccount)
        {
            const int accountId = -1;
            var account = isExistingAccount ? new Account() : null;
            A.CallTo(() => AccountService.GetAccount(accountId)).Returns(account);

            var result = (IStatusCodeActionResult)_controller.GetAccount(accountId);

            var statusCode = isExistingAccount ? HttpStatusCode.OK : HttpStatusCode.NotFound;
            result.StatusCode.Should().Be((int)statusCode);

Я попытался написать универсальный метод для подделки.

        public void GetEntityActionMethodTest<TEntityType>(bool isExisting, Func<int, TEntityType> serviceMethod, Func<int, ActionResult> actionMethod) where TEntityType : class
        {
            var fakeMethod = A.Fake<Func<int, TEntityType>>();
            A.CallTo(() => fakeMethod(-1)).Returns( isExisting ? default(TEntityType) : null);
            var result = (IStatusCodeActionResult)actionMethod(-1);
            result.StatusCode.Should().Be(isExisting ? (int)HttpStatusCode.OK : (int)HttpStatusCode.NotFound);
        }

Есть две проблемы:

1) Не фальсифицируется правильно, чтобы вернуть ноль

2) Предполагается, что метод интерфейса имеет один целочисленный параметр

Вопросы

1) Является ли хорошей идеей работать над созданием универсального метода, который может имитировать методы, которые могут иметь разные подписи в разных интерфейсах, используя FakeItEasy? Как насчет отражения?

2) Если да, как я могу это сделать?

Спасибо.

1 Ответ

0 голосов
/ 16 мая 2019

Я не совсем уверен, какова ваша цель. Вы говорите, что пытаетесь написать универсальный метод для подделки, но ваш пример выглядел как полный тест. Я расскажу о том, как сделать подделку. Включение его в тесты должно быть простым.

Если цель состоит в создании фальшивки, которая будет возвращать определенный объект при вызове любого метода, параметризованного фальшивым типом и возвращаемым значением, вы можете использовать методы пространства имен FakeItEasy.Sdk для создания объект, и вы можете настроить подделку на ответить на любой метод , например, так:

public object CreateFakeWithReturnValue(Type typeOfFake, object returnValue)
{
    var fake = Create.Fake(typeOfFake);
    A.CallTo(fake).WithNonVoidReturnType().Returns(returnValue);
    return fake;
}

Конечно, этот метод можно сделать более сложным, посмотрев на переданный вызов (или, если вы знаете тип подделки, вы можете сделать этот метод универсальным и просто использовать стандартную конструкцию A.Fake).

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

...