如何模拟作为函数输入的对象?

时间:2019-10-07 12:57:22

标签: python testing mocking

通常,当我嘲笑时,我具有以下类型的设置

# my_script.py
import numpy as np

def my_func(x):
    out = np.power(x, 2)
    return out

然后在power中测试numpy my_script调用:

# test_myscript.py

import numpy as np
import unittest
import mock

from my_script import my_func


class TestMyScript(unittest.TestCase):

    @mock.patch("my_script.np")
    def test_my_func(self, mock_os):
        """Test that numpy.power was called"""
        a = np.array([1, 2, 3])
        my_func(a)
        mock_os.power.assert_called_with(a, 2)


if __name__ == '__main__':
    unittest.main()

这很好。

但是现在情况发生了变化,并说我将numpy模块作为 argument 传递给my_func;在这种情况下,我不知道如何模拟numpy

如何在下面的函数中模拟numpy,就像在上面的test_myscript中模拟一样?

请注意,numpy不会导入my_script.py中,而是会导入运行my_script.py中的函数的单独脚本中。

# my_script.py
# numpy NOT imported in this script!

def my_func(x, numpy):
    out = numpy.power(x, 2)
    return out

编辑:

基于@Daniel Roseman的评论,我包括一些其他代码,以明确说明函数的调用方式

# main_script.py

import numpy as np

from my_script import my_func

def main():
    a = np.array([1, 2, 3])
    my_func(a, np)  # numpy is passed into `my_func`

然后进行测试,我正在尝试以下

# test_myscript.py

import numpy as np
import unittest
import mock

from my_script import my_func

class TestMyScript(unittest.TestCase):

    @mock.patch("main_script.np")  # import from main_script since numpy is imported here
    def test_my_func(self, mock_os):
        """Test that numpy.power was called"""
        a = np.array([1, 2, 3])
        my_func(a)
        mock_os.power.assert_called_with(a, 2)


if __name__ == '__main__':
    unittest.main()     

但这失败了

Ran 1 test in 0.154s
>>> FAILED (failures=1)
>>> AssertionError: Expected 'power' to have been called.

1 个答案:

答案 0 :(得分:2)

我发现在这里使用unittest.mock.Mock对象效果最好。

所以,如果我们有:

# my_script.py

def my_func(x, numpy):
    out = numpy.power(x, 2)
    return out

然后测试一下我们有

# test_myscript.py

import numpy as np
import unittest
from unittest.mock import Mock

from my_script import my_func

numpy_mock = Mock()


class TestMyScript(unittest.TestCase):

    def test_my_func(self):
        """Test that numpy.power was called"""
        a = np.array([1, 2, 3])
        _ = my_func(a, numpy_mock)  # pass the mocked object here
        numpy_mock.power.assert_called_once_with(a, 2)


if __name__ == '__main__':
    unittest.main()  

通过考试