Мокающий ответ для преобразователя запросов 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 Client запускать запрос, он дает мне «немодельный» ответ. Другими словами, фактически вызывает исходный метод, предоставленный классом объекта службы, и выполняет вызовы API, что не должно выполняться. Однако, когда я создаю и запускаю сам класс ServiceObject, он правильно имитирует и возвращает массив ['baz', 'qux'], не проходя через вызовы API.

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

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

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


person Lucas Charles    schedule 21.01.2019    source источник
comment
Возможно написать успешные тесты с графеном, если вы не пытаетесь имитировать его - например, см. stackoverflow.com/questions/45493295/testing-graphene-django/   -  person Mark Chackerian    schedule 22.01.2019
comment
Трудно сказать без минимального воспроизводимого примера. Возможно, вы исправляете неправильный Foo или ваш производственный код не выполняет то, что вы думаете. Получить patch правильно довольно сложно, издевательство намного проще, если вы используете инъекцию зависимостей. Кроме того, вы, похоже, тестируете в основном сторонний код.   -  person Stop harming Monica    schedule 22.01.2019


Ответы (1)


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

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

Чтобы доказать, что

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, который пришел на помощь, когда я спросил в Github-репозиторий Graphene-Python.

person Lucas Charles    schedule 22.01.2019