首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用python、pytest、mock在另一个模块中模拟第三方函数

使用python、pytest、mock在另一个模块中模拟第三方函数
EN

Stack Overflow用户
提问于 2018-07-13 02:03:53
回答 2查看 3.2K关注 0票数 2

我有一个func1()函数,它正在生产中,不能修改。它调用另一个模块中的函数function_to_be_mocked()。它接受输入参数。

我还有另一个调用func1()的函数func2()。

我正在编写单元测试来测试func2(),并试图模拟function_to_be_mocked (因为它依赖于一些我在本地系统上没有(也不应该有)的键)。我唯一能修改的就是test_func2()。

我有一个如下所示的设置(最小示例):

代码语言:javascript
复制
from othermodule import function_to_be_mocked
import pytest
import mock

def func1():
    function_to_be_mocked(None)

def func2():
    ret = func1()
    print (ret)

@mock.patch('othermodule.function_to_be_mocked', return_value = 3)
def test_func2(mocker):
    func2()

othermodule.py是:

代码语言:javascript
复制
def function_to_be_mocked(arg1):
    if not arg1 == 'foo':
        raise ValueError

我的输出:

直接调用func2:

代码语言:javascript
复制
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/blah/temp.py", line 9, in func2
    ret = func1()
  File "/Users/blah/temp.py", line 6, in func1
    function_to_be_mocked(None)
  File "/Users/blah/othermodule.py", line 3, in function_to_be_mocked
    raise ValueError
ValueError

调用test_func2(),我希望它会被嘲笑:

代码语言:javascript
复制
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/blah/venv/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "/Users/blah/temp.py", line 14, in test_func2
    func2()
  File "/Users/blah/temp.py", line 9, in func2
    ret = func1()
  File "/Users/blah/temp.py", line 6, in func1
    function_to_be_mocked(None)
  File "/Users/blah/othermodule.py", line 3, in function_to_be_mocked
    raise ValueError
ValueError

因此,模拟似乎不起作用。有没有人有什么想法可以做到这一点?

在此行===========下编辑的============

听起来我不能做我认为我能做的事情(因为我不能修改与函数1或2相关的任何东西。我唯一能控制的就是考试。

那么,让我提出以下问题,因为也许比我更有经验的眼睛可以看到前进的方向。

我有一个函数:

代码语言:javascript
复制
def function_to_be_tested(args):
    # Some processing steps

    # Function call that works locally
    function_that_returns_something_1()

    # Some logic

    # Function call that works locally
    function_that_returns_something_2()

    # Function that raises an exception when running locally,
    # and since I need to test the logic after this function 
    # (and cannot edit this code here to bypass it) I would 
    # (naively) like to mock it.
    function_I_would_like_to_mock()

    # Much more logic that follows this function. 
    # And this logic needs to be unit tested.
    return some_value_based_on_the_logic

测试:

代码语言:javascript
复制
def test_function_to_be_tested():
    assert function_to_be_tested(args) == some_expected_value

在function_I_would_like_to_mock()之前,我可以很容易地对任何东西进行单元测试。

但是由于这个函数在本地崩溃(我不能编辑代码来阻止它在本地崩溃),我觉得正确的方法应该是模拟它并强制一个合理的返回值。这样我就可以单元测试超出这个范围的代码路径了。

你建议什么是一个好的方法?

请注意,我唯一可以修改的是test函数。我甚至不能在主函数中添加装饰器。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-13 02:34:11

选项A)

您希望模拟的函数将加载到func1中。因此,您必须将@patch装饰器应用于func1

代码语言:javascript
复制
import pytest
from unittest import mock

@mock.patch('othermodule.function_to_be_mocked', return_value = 3)
def func1(mocker):
    from othermodule import function_to_be_mocked
    function_to_be_mocked(None)

def func2():
    ret = func1()
    print (ret)

def test_func2():
    func2()

test_func2()

=========Edit===========

选项B)

代码语言:javascript
复制
import pytest
from unittest import mock


def func1():
    from othermodule import function_to_be_mocked
    function_to_be_mocked(None)

def func2():
    ret = func1()
    print (ret)

def test_func2():
    with mock.patch('othermodule.function_to_be_mocked', return_value = 3) as irrelevant:
        func2()

test_func2()
票数 2
EN

Stack Overflow用户

发布于 2022-02-26 03:46:24

如果你想模拟一个来自python中另一个模块中的模块内函数的函数,你可以试试这个。

代码语言:javascript
复制
 # application2.py
 def app2_func(a):
           print(a)
代码语言:javascript
复制
 # application1.py
 import application2
def app1_func(a):
    application2.app2_func(a) # func to be mocked 

用于测试函数的测试文件

代码语言:javascript
复制
   # application_test.py
    import application1
    def test_app1_func(mocker):
       app2_mocker = mocker.patch('application1.application2.app2_func')
       application1.app1_func('mock call')
       app2_mocker.assert_called_once() # to check if mocked function is called once
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51311935

复制
相关文章

相似问题

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