[大阪/横滨/德岛] 寻找基础设施/服务器端工程师!

[大阪/横滨/德岛] 寻找基础设施/服务器端工程师!

【超过500家企业部署】AWS搭建、运维、监控服务

【超过500家企业部署】AWS搭建、运维、监控服务

【CentOS的后继者】AlmaLinux OS服务器搭建/迁移服务

【CentOS的后继者】AlmaLinux OS服务器搭建/迁移服务

[仅适用于 WordPress] 云服务器“Web Speed”

[仅适用于 WordPress] 云服务器“Web Speed”

[Python]仅此而已! pytest模拟的摘要!

你好!
我是系统开发部的福井!

现在,我撰写此博客的2025年的十二生肖是“蛇”,所以
Python测试框架Pytest的模拟

标题上写着“模拟摘要”,但我专注于根据自己的个人观点和偏见选择的功能和用法,并根据自己的经验以及我想牢记的。

因此,我希望这对从未尝试过pytest或计划将来使用它的任何人都有帮助。

介绍

[介绍]

作为先决条件,此博客基本上将pytest mock的pytest插件的代码
请注意,符号与
python标准库中的unittest.mock该博客不会解释
UniteSt.Mock https://docs.python.org/3/library/unittest.mock.html

[对于那些还没有触摸pytest的人]

我还将包括一些示例测试代码,但是如果您尚未尝试过Pytest,我们将感谢您的阅读。

以下是在测试方法中实现的模拟的示例,但中的嘲讽
Pytest Mock提供的固定装置因此,如果安装了pytest mock,则可以使用它而无需进口或其他特殊需求。

1
def test_get_name(嘲弄):oigher.patch.object(((省略))

这个博客没有解释“什么是固定装置?”或“什么是嘲笑者?
https://docs.pytest.org/en/stable/
https://pypi.org/project/project/pytest-mock/

模拟方法属性

现在,让我们来到主要故事。
首先,我们将解释如何模拟方法和属性。

模拟实例方法

首先,我们将向您介绍模拟实例方法,这些方法可能在许多情况下使用。
例如,如果有一个名为UserInfo的类,并且定义了返回str的值(称为get_name()的值的方法,则是定义的,则实现示例将是:

1
def test_get_name(模拟器):test_name =“ testname”#get_name()of userInfo class oigher.patch.patch.object(userInfo,“ get_name”,return_value = test_name)中的get_name()模拟)

为第一个和第二个参数指定
类对象和方法并且要指定返回值,请指定return_value的值,然后完成。

特定模块的模拟方法

如果要模拟一类未定义的方法,也可以指定一个模块并按以下方式模拟它:

1
def test_get_name(模拟器):test_name =“ testname”#app.services.services.user module模块oigher.patch(“ app.services.services.user.get_name”,return_value = test_name)

模拟是通过指定
目标模块以及在模块中执行的字符串的方法实施此功能时,请注意不要在模块规范中犯任何错误。

当多次执行相同方法时,用不同的返回值模拟

在某些情况下,正在测试的方法多次执行另一种相同的方法。
如果返回值已固定,则可以使用上述方法测试和实现测试,但是根据过程,处理路由可能会根据返回值而更改。

这种情况的一个有用的部分是side_effect 实施示例如下:

1
def test_get_name(mocker): test_name_1 = "Tanaka Ichiro" test_name_2 = "Suzuki Jiro" # Mock of get_name() in the UserInfo class mocker.patch.object( UserInfo, 'get_name', side_effect=[ test_name_1, # Return value when executed for the first time test_name_2, # Return value when executed for the second time] )

side_effect是一个方便的属性,可允许您自定义模拟目标的行为,并且在上面的示例之外还可以指定功能,但是我会跳过此主题,因为它偏离了主要主题。
返回主要主题,如果要为每个执行次数指定一个不同的值,按照您要返回的值的顺序指定它来设置它,
Side_Feft将以其他方式引入,这是一项方便的功能,可以通过多种方式使用。

模拟属性

如果您想模拟属性,而不仅仅是方法,还可以使用
PropertyMock例如,如果UserInfo类具有一个名为first_name的属性,该名称存储该名称,则实现示例如下:

1
def test_first_name(oigher):first_name_taro =“ taro”#模拟userInfo Mocker.patch.object.object(userInfo,“ first_name”,new_callable',new_callable = property = property_value = first_name_taro)的first_name属性

PropertyMock本身是标准Python库Unittest.Mock提供的类,用于模拟特定类的属性,例如本文中。 (这与普通模拟中使用的模拟类别不同。)
代码本身与模拟方法没有什么不同,但是请注意,需要new_callable,例如new_callable = PropertyMock

验证模拟执行

到目前为止,我们已经介绍了如何模拟方法和属性,但是
在实际实施单元测试时,有时您想验证
是否按预期调用模拟过程从这里, 我们将向您介绍验证执行模拟方法

验证是否执行

现在,让我向您展示如何首先验证它是“是否执行”。
如果要简单地是否被调用一次assert_called_once()的方法实现它
实施示例如下:

1
def test_get_name(mocker): test_name = "testname" # Mock of get_name() in the UserInfo class mock_get_name = mocker.patch.object( UserInfo, "get_name", return_value=test_name ) (※Method execution processing, etc.) # Mocking of get_name() has been executed once mock_get_name.assert_called_once()

如果要验证多次,
surstertcall_count的属性来实现它们,如下所示

1
def test_get_name(模拟器):test_name =“ testname”#get_name()ofuserInfo class mock_get_get_get_get_name = oiker.patch.object.object.object.object(userInfo,“ get_name”,return_value = test_name)(test_name)(*mock_name)#opt_name(deccopt_name)

 

验证是否通过预期参数执行

接下来,我们将介绍如何验证
传递给模拟方法的论点是否如预期可以使用方法
assert_called_with()这一点实施示例如下:

1
def test_get_name(嘲笑器):test_name =“ testname”#参数的预期值传递给了oferinfo class_get_get_name = mock_name.patch.patch.object.object.object.object.object(userInfo),get_name(userInfo)的get_name(use_name get_name = get_ get_name decortion) value(Expection_USER_ID)MOCK_GET_NAME.ASSERT_CALLED_WITH(USER_ID = Expection_user_id)

一起验证“是否被执行”和“参数”

到目前为止,我们已经介绍了验证该方法是否已执行以及是否单独预期的方法,但是也有一种方法可以一起验证此问题。
使用方法
assert_called_once_with() 实施示例如下:

1
def test_get_name(嘲笑器):test_name =“ test Name”#参数的预期值传递给了ofuse_get_get_get_name = mocker.patch.patch.object.object.object.object.object.object.object.object.object.obignt(userInfo) _USER_ID)并执行一次MOCK_GET_NAME.ASSERT_CALLED_ONCE_WITH(USER_ID = Expection_user_id)

如果您假设要模拟的方法仅调用一次,那么最好简单地使用ASSERT_CALLED_ONCE_WITH()而不是assert_called_with()

即使模拟的方法被多次称为称为也可以使用
ASSERT_HAS_CALLS()实施示例如下:

1
def test_get_name(嘲弄):test_name_1 =“ tanaka iChiro” test_name_2 =“ suzuki jiro” get_name',side_effect = [test_name_1,#首次执行test_name_2执行时返回值,第二次执行时返回值])嘲弄(expect_user_id_tanaka),嘲讽。

将论点传递给模拟方法

另外,尽管这不是上述验证方法,但您也可以检索
传递给模拟方法的参数call_args.args模拟对象的获得
获得的值是元组类型的,可以作为位置参数检索。
实施示例如下:

1
def test_get_name(嘲笑):test_name =“ testName”#get_name()模拟userInfo class mock_get_get_get_get_name = oigher.patch.object.object.object(userInfo,“ get_name”,return_value = test_name) args [0]#第二个参数args_2 = args [1]

如果可以获得论点,您可以使用断言来验证它们(尽管可能无需故意使用断言...),
您也可以使用所获得的参数来编写其他过程,因此我个人想记住这一点并介绍了这些过程。
但是,请注意, call_args只能检索“最后执行中的参数” ,因此,如果要检索多次执行的方法的参数,请使用call_args_list

使用side_effect提高例外

最后,我们将向您展示如何使用模拟对象提出异常。
我们将使用
side_effect ,该effect在另一个主题中出现实施示例如下:

1
def test_get_name(oigher):test_error_message =“目标用户不存在”#用UserInfo class mock_get_get_name = mocker.patch.object.object.object(userInfo,userInfo,“ get_name”,side_effect = except_effect = exception(test_error_message))

实现本身也很简单,要为side_effect提出的异常类实例来完成该过程
如果正在发生异常时测试的方法正在执行某些操作,则可以使用此方法在发生异常时通过处理路线来增加测试的覆盖范围。

概括

你怎么想?
在此博客中,我们介绍了根据我们使用的情况所使用的方法和实现方法,但我认为代码本身易于实现。
另外,正如我一开始写的那样,我只专注于我想记住的内容,因此,将其朝相反的方向放在这里,这里仍然有很多功能和方法在这里介绍。
如果您有兴趣,请参考官方文档,以找出更好的实现和有用的功能!
仅此而已!下次见!

如果您觉得这篇文章有帮助,请点赞!
4
加载中...
4 票,平均:1.00 / 14
237
X Facebook 哈特纳书签 口袋
[2026.6.30 Amazon Linux 2支持端] Amazon Linux服务器迁移解决方案

[2026.6.30 Amazon Linux 2支持端] Amazon Linux服务器迁移解决方案

写这篇文章的人

关于作者

福井宏人

2020年6月加入Beyond。
在系统开发部(横滨办事处)工作。 在工作中,我主要负责游戏API和Web系统的开发,以及Shopify私有应用程序的开发,主要使用PHP。
我总体上喜欢音乐,主要是西方音乐,并以弹吉他为爱好。 他最喜欢的电视节目是《侦探!夜景》和《闹鬼!广告街天堂》。