python 使用可选参数模拟函数

xxhby3vn  于 2023-03-11  发布在  Python
关注(0)|答案(2)|浏览(152)

我想写一个测试“A”函数调用另一个“B”函数。B函数看起来像这样:

def Bfuncion(self, city: Optional[str], name: Optional[str]):

在A函数中,我使用了B函数两次,第一次是这样使用:

cities = self.Bfunction(name=None, city="ny", page=page)

第二次是这样的

cities = self.Bfunction(name="Tom", city=None, page=page)

现在我想写一个测试的A函数,我会尝试如果只有一个使用B函数:

mocker.patch(
        "Path.To.My.Function",
        return_value=[
            {"someReturnValue"},
            {"someReturnValue"},
            {"someReturnValue"},
        ],

如何编写call mocker(),因为我在每次调用中使用了带有不同参数的B函数。

nx7onnlm

nx7onnlm1#

使用side_effect关键字参数,而不是return_value关键字参数。

>>> from unittest.mock import Mock
>>> m = Mock(return_value=[1,2,3])
>>> m()
[1, 2, 3]
>>> m = Mock(side_effect=[1,2,3])
>>> m()
1
>>> m()
2
>>> m()
3

(当然,patch只是简单地将它自己无法识别的关键字参数传递给Mock,以配置修补名称所使用的对象。)
这就要求你提前知道调用的顺序,如果你需要更大的灵活性,用一个你想要的自定义函数来代替Mock对象。

def my_func(self, name, city, page):
    ...
mocker.patch(
    "Path.To.My.Function",
    new=my_func
)
yiytaume

yiytaume2#

我试着给你一个解答我不知道这是否适合你的需要,因为我曾尝试猜测你在问题中遗漏的一些细节。

生产代码

我假设您的产品代码包含在一个名为functions.py的文件中,functions.py的内容如下:

from  typing import Optional

class MyClass:

    def Bfunction(self, city: Optional[str], name: Optional[str]):
        return city

    def Afunction(self):
        cities = self.Bfunction(name=None, city="ny", page='page')
        print(cities)
        cities = self.Bfunction(name="Tom", city=None, page='page')
        print(cities)

请注意,在functions.py中:
1.我定义了一个类,因为我看到您的Bfunction定义包含self参数。

  1. Afunction执行您在问题中编写的两个Bfunction调用。

测试文件

测试文件(不使用pytest,仅使用模块unittest)如下所示:

import unittest
from unittest import mock
import functions

class MyTestCase(unittest.TestCase):

    def test_something(self):
        sut = functions.MyClass()
        with mock.patch.object(sut, 'Bfunction') as mock_b:
            # set values returned by Bfunction in the first and in the second call
            mock_b.side_effect = ['cityA', 'cityB']
            sut.Afunction()
            # here I verify that Bfunction is called 2 times
            self.assertEqual(2, mock_b.call_count)

            # here I verify the arguments of the Bfunction 2 calls
            self.assertDictEqual({'name': None, 'city': 'ny', 'page': 'page'},
                                 mock_b.call_args_list[0][1])
            self.assertDictEqual({'name': 'Tom', 'city': None, 'page': 'page'},
                                 mock_b.call_args_list[1][1])

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

测试文件执行的输出

测试文件执行的输出为:

cityA
cityB
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

输出显示:

  1. Afunction调用的次数正好是Bfunction的两倍
    1.测试验证通过使用属性call_args_list传递给Bfunction的参数
    1.输出中cityAcityB的出现向您展示了如何选择Bfunction返回的不同值(您必须使用side_effect而不是return_value)。
    我希望这个答案对你有用。

相关问题