从ServiceObject模拟GraphQL查询解析器的响应,以防止在UnitTests中调用API

时间:2019-01-21 19:46:20

标签: python automated-tests graphql graphene-python

假设我具有以下服务对象:

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 Client的响应?有什么方法可以代替模拟吗?

我已经遍及整个互联网,看看人们是如何做到的,但是我无法找到任何可能的解决方案。

1 个答案:

答案 0 :(得分:0)

所以,问题是:

我的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 repository中询问时,他进行了救援。