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

Posted

技术标签:

【中文标题】模拟来自 ServiceObject 的 GraphQL 查询解析器的响应,以防止在 UnitTests 中调用 API【英文标题】:Mocking response for GraphQL query resolver from ServiceObject to prevent API calls in the UnitTests 【发布时间】:2019-06-15 05:58:07 【问题描述】:

假设我有以下服务对象:

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 Schema 是否在其查询解析器中正确调用了方法 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 是否正在调用将返回其假定对象的方法。

问题

当我像上面的代码那样模拟服务对象返回的响应,并使石墨烯客户端测试运行查询时,它给了我“非模拟”响应。也就是说,其实是调用服务对象类提供的原始方法,进行API调用不应该进行。但是,当我实例化并运行 ServiceObject 类本身时,它会被正确模拟并返回 ['baz', 'qux'] 数组,而不是通过 API 调用。

有人知道我做错了什么吗?

或者根本不应该嘲笑 GraphQL 客户端响应?有什么方法可以代替嘲笑它吗?

我已经在整个互联网上查看了人们是如何做到这一点的,但我无法找到任何可能的解决方案。

【问题讨论】:

如果你不尝试模拟它,它可能会用石墨烯编写成功的测试——例如参见***.com/questions/45493295/testing-graphene-django/… 如果没有minimal reproducible example 就很难说。可能是您修补了错误的Foo,或者可能是您的生产代码没有按照您的想法执行。让patch 正确是相当困难的,如果你使用依赖注入,模拟会容易得多。此外,您似乎主要在测试第三方代码。 【参考方案1】:

所以,问题是:

我的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 中询问时,他出手相救。

【讨论】:

以上是关于模拟来自 ServiceObject 的 GraphQL 查询解析器的响应,以防止在 UnitTests 中调用 API的主要内容,如果未能解决你的问题,请参考以下文章

常见排序算法-----希尔排序

来自 void 类的模拟异步调用

模拟来自不同位置的 HTTP 请求 - ASP.Net

来自 Guzzle 的 PHPUnit 和模拟请求

来自 Storybook 的模拟 api 调用

Python - 模拟当前登录的用户(来自系统用户)