首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用pytest-mock有条件地模拟函数

如何使用pytest-mock有条件地模拟函数
EN

Stack Overflow用户
提问于 2021-02-26 13:55:58
回答 1查看 5K关注 0票数 0

我在foo.py中有一个类,我想测试:

代码语言:javascript
复制
import requests

class Foo:
    def fooMethod(self, url):
        response = requests.get(url)
        return response

我想替换requests调用来模拟响应。

这是我的test_foo.py测试文件

代码语言:javascript
复制
from foo import Foo

def mocked_requests_get(*args, **kwargs):
    class MockResponse:
        def __init__(self, text, code):
            self.text = text
            self.code = code
    
    if args[0] == "http://localhost":
        return MockResponse("Test response", 200)

    return MockResponse(None, 404)


class TestFoo:
    def test_foo(self, mocker):
        a = Foo()
        mocker.patch ('foo.requests.get', mocked_requests_get)
        spy = mocker.spy (a, 'test_foo.mocked_requests_get')
        response = a.fooMethod("http://localhost")
        assert response.text == "Test response"
        assert spy.call_count == 1

我想检查是否只调用了一次mocked_requests_get函数。

解释器在spy = mocker.spy ...行上出现一个错误:

代码语言:javascript
复制
'Foo' object has no attribute 'test_foo.mocked_requests_get'

这是可以理解的--但我无法找到引用该函数的对象实例。有人能帮忙吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-26 14:26:25

您的方法有点复杂-您可以只使用一个标准模拟,而不需要实现您自己的模拟类。像这样的事情应该有效:

代码语言:javascript
复制
class TestFoo:
    def test_foo(self, mocker):
        a = Foo()
        get_mock = mocker.patch('requests.get')
        get_mock.return_value.text = "Test response"
        response = a.fooMethod()
        assert response.text == "Test response"
        assert get_mock.call_count == 1

还要注意,您必须修补requests.get而不是foo.requests.get,因为您直接导入了requests (参见打补丁的地方)。

更新:

如果需要响应依赖于url,如更新的问题中所示,可以使用side_effect,它可以接受函数或类对象(除非return_value需要一个求值的值):

代码语言:javascript
复制
class MockedResponse:
    def __init__(self, url):
        self.url = url

    @property
    def text(self):
        responses = {"url1": "response1",
                     "url2": "response2",
                     "url3": "response3"}
        if self.url in responses:
            return responses[self.url]
        return "default"


class TestFoo:
    def test_foo(self, mocker):
        a = Foo()
        get_mock = mocker.patch('requests.get')
        get_mock.side_effect = MockedResponse
        response = a.fooMethod("url2")
        assert response.text == "response2"
        assert get_mock.call_count == 1
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66387081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档