Ложный ответ для распознавателя запросов GraphQL из ServiceObject для предотвращения вызовов API в UnitTests

Давайте предположим, что у меня есть следующий сервисный объект:

class Foo(object):
    def bar(self):
        return ['foo', 'bar']

И это схема:

import Foo

class Query(graphene.ObjectType):
    bar = graphene.List(lambda: graphene.String)

    def resolve_bar(self, info):
        return Foo().bar()

Я пытаюсь проверить, правильно ли схема GraphQL вызывает метод bar в своем преобразователе запросов. Итак, у нас есть этот кусок кода в тестах:

from MySchema import Query

class TestFooBar(unittest.TestCase):
    @patch('Foo')
    def test_bar(self, mock_foo):
        mock_foo.return_value.bar.return_value = ['baz', 'qux']

        my_schema = graphene.Schema(query=Query)
        client = Client(self.my_schema)

        query = '''
            query {
                bar()
            }
        '''
        executed = self.client.execute(query)

       #some attributes that I want to assert
       assertTrue(mock_foo.called) # returns False

Почему я использую издевательства?

В исходном классе ServiceObject он выполняет некоторые вызовы API для другой службы, которая уже тестируется изолированно. И в этом случае я только хочу проверить, если запрос GraphQL bar вызывает метод, который вернет предполагаемый объект.

Эта проблема

Когда я высмеиваю ответ, который возвращает сервисный объект, как в приведенном выше коде, и заставляю тест клиента Graphene выполнить запрос, он дает мне "немодированный" ответ. Другими словами, это фактически вызов исходного метода, предоставленного классом объекта службы, и выполнение вызовов API, которые не должны выполняться. Однако, когда я создаю экземпляр и запускаю сам класс ServiceObject, он корректно проверяется и возвращает ['baz', 'qux'] массив, не проходящий через вызовы API.

У кого-то есть представления о том, что я делаю неправильно?

Или ответы клиента GraphQL вообще не должны поддразнивать? Есть ли какой-нибудь подход, который я могу использовать вместо насмешек?

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

2 ответа

Решение

Итак, проблема в том, что:

мой patch неправильно. Я должен исправить патч, а не сайт определения. В этом случае это будет: @patch('MySchema.Foo') выполнить издевательство над паролем.

Чтобы доказать это

from MySchema import Query

class TestFooBar(unittest.TestCase):
    @patch('MySchema.Foo')
    def test_bar(self, mock_foo):
        mock_foo.return_value.bar.return_value = ['baz', 'qux']

        my_schema = graphene.Schema(query=Query)
        client = Client(self.my_schema)

        query = '''
            query {
                bar()
            }
        '''
        executed = self.client.execute(query)

        assertTrue(mock_foo().bar.called) # now returns True

Спасибо jkimbo, который пришел на помощь, когда я спросил в репозитории Graphene-Python Github.

Я знаю, что этот вопрос касается Graphene , но у меня была такая же проблема (насмешка над распознавателем graphql) с Ariadne , и я написал это решение для других, таких как я, у которых нет доступа к достаточному количеству документов о модульных тестах graphql с ariadne.

Как сказано в принятом ответе, имитирующего распознавателя недостаточно, и graphql по-прежнему вызывает неискаженный распознаватель. Поэтому мы должны изменить схему, чтобы вызывать эту новую функцию вместо основного преобразователя. И, в моем случае, измените URL-адрес django, чтобы использовать новую исполняемую схему.

      from .urls import urlpatterns
with patch('path.to.my_resolver') as mocked_resolver:
    query = QueryType()
    query.set_field(mocked_field, mocked_resolver)
    mocked_resolver.return_value = mocked_return_value
    my_schema = make_executable_schema(my_base_schema, query, snake_case_fallback_resolvers)
    urlpatterns.clear() # remove main urls
    urlpatterns.append(path('graphql/', GraphQLView.as_view(schema=my_schema), name='graphql'))

Примечание: snake_case_fallback_resolvers из-за обработки декоратора convert_kwargs_to_snake_case .

Другие вопросы по тегам