为了账号安全,请及时绑定邮箱和手机立即绑定

使用 @patch() 模拟和不使用 side_effect 有什么区别?

使用 @patch() 模拟和不使用 side_effect 有什么区别?

SMILET 2022-05-24 09:16:08
我有一个script.py文件:# in script.pydef my_basic_function(value, c):    return c(value).words()class BasicClass:    def __init__(self, val):        self.val = val    def words():        return self.val和一个test.py文件:# in test.pyfrom mock import patchfrom script import my_basic_function, BasicClassdef third_function(self,):    return "not {}".format(self.val)def fourth_function():    return "not ponies"def init_mock(self, val):    self.val = val@patch('script.BasicClass.words', third_function)@patch('script.BasicClass.__init__', init_mock)def test_my_basic_function():    assert my_basic_function("ponies", BasicClass) == "not ponies"我可以pytest test.py从命令行成功运行。如果我想side_effect在 my中使用@patch,我必须做一些不同的事情:@patch('script.BasicClass.words', side_effect = fourth_function)@patch('script.BasicClass.__init__', init_mock)def test_my_basic_function(amock):    assert my_basic_function("ponies", BasicClass) == "not ponies"即,我必须:添加一个test_my_basic_function我从不使用的参数。callfourth_function而不是third_function,因为我不能使用任何类实例变量。这两种方式打补丁有什么区别?
查看完整描述

1 回答

?
慕仙森

TA贡献1827条经验 获得超8个赞

您不需要为您正在做的事情打补丁(示例 A)。您正在传递参数 c,您知道它是 BasicClass 的类,因此不需要补丁。如果您在您不希望实际发生的测试函数中引入了函数调用或对象初始化,您将需要一个补丁。


使用时@patch我们应该使用 kwargside_effect来模拟异常的引发,而不是调用其他函数。如果我们想模拟函数的返回值,请使用 kwarg return_value。如果我们只是想模拟一个函数,那么我们只需使用@patch没有任何 kwargs。当我们使用补丁作为装饰器时,我们需要将它们传递给函数。确实可以不用它们,但我们应该将它们与模拟函数一起使用,例如assert_called_once或assert_called_once_with以确保您的补丁按预期工作。请参见示例 B


==============示例A==================


import unittest



def my_basic_function(value, c):

    return c(value).words()



class BasicClass:

    def __init__(self, val):

        self.val = val


    def words(self):

        return self.val



class TestMyBasicFunction(unittest.TestCase):


    def test_my_basic_class(self):

        value = my_basic_function("jeremy", BasicClass)

        self.assertEqual("jeremy", value)


    def test_my_basic_class_wrong(self):

        value = my_basic_function("jeremy", BasicClass)

        self.assertNotEqual("w33b", value)

============示例B======================


import unittest

from unittest.mock import patch



def ensure_str(value):

    try:

        return str(value)

    except Exception:

        raise TypeError



def my_basic_function(value, c):

    value = ensure_str(value)

    return c(value).words()



class BasicClass:

    def __init__(self, val):

        self.val = val


    def words(self):

        return self.val



class TestMyBasicFunction(unittest.TestCase):


    @patch('script.ensure_str', return_value="jeremy")

    def test_return_value(self, ensure_str_mock):

        value = my_basic_function("jeremy", BasicClass)

        ensure_str_mock.assert_called_once_with("jeremy")

        self.assertEqual("jeremy", value)


    @patch('script.ensure_str')

    def test_no_return_value(self, ensure_str_mock):

        value = my_basic_function("jeremy", BasicClass)

        self.assertEqual(ensure_str_mock(), value)


    @patch('script.ensure_str', side_effect=TypeError)

    def test_side_effect(self, ensure_str_mock):

        with self.assertRaises(TypeError):

            value = my_basic_function({'apple': 'sauce'}, BasicClass)

        ensure_str_mock.assert_called_once_with({'apple': 'sauce'})


查看完整回答
反对 回复 2022-05-24
  • 1 回答
  • 0 关注
  • 204 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号