gpt4 book ai didi

python - 如何正确模拟类(class)的私有(private)成员

转载 作者:行者123 更新时间:2023-11-28 22:11:41 24 4
gpt4 key购买 nike

我正在尝试为依赖于另一个私有(private)方法的方法编写一些单元测试。 - 如下例所示:

def is_member_of(self, group_name):
members = self.__get_group_members(group_name)

我想模拟的私有(private)方法是__get_group_members;我还想模拟私有(private)属性 __user_id,因为它将在 is_member_of 函数中使用(上例中未显示)。

我目前拥有的:

import unittest
from unittest import mock

class Test(unittest.TestCase):
group_data = []
user_id = 'test_user_id'

def mock_dependencies(self, x):
x.__user_id = mock.PropertyMock(return_value=self.user_id)
x.__get_group_members = mock.MagicMock(return_value=self.group_data)

def first_test(self):
x = A(('name', 'group'))
self.mock_dependencies(x)
x.is_member_of('test_group')

当我调用 x.is_member_of() 时,模拟无法按预期工作。

最佳答案

您可以在 Python 中访问私有(private)属性,因为 private 和 protected 是约定俗成的。 - 您正在寻找的基本上是使用 _ClassName__private_attribute_name,因为 python 执行重命名以实现约定的公约。

示例(返回 MagicMock):

with mock.patch.object(Class, '_ClassName__private_attribute_name', return_value='value') as obj_mock:
pass

示例(返回原始值):

with mock.patch.object(Class, '_ClassName__private_attribute_name', new_callable=PropertyMock) as obj_mock:
obj_mock.return_value = 'string value'

Class 是对类本身的引用 - 而不是实例。

完整示例:

from unittest.mock import patch, PropertyMock
from unittest import TestCase, main


class Private:
__attr = 'hello'


class PrivateTest(TestCase):
@patch.object(Private, '_Private__attr', new_callable=PropertyMock)
def test_private_attribute_value_change_decorator_success(self, private_mock):
obj = Private()
private_mock.return_value = 'string'

self.assertEqual('string', obj._Private__attr)

def test_private_attribute_value_change_context_manager_success(self):
with patch.object(Private, '_Private__attr', new_callable=PropertyMock) as o_mock:
obj = Private()

o_mock.return_value = 'mocked value'
self.assertEqual('mocked value', obj._Private__attr)


if __name__ == '__main__':
main()

对示例的修改:

from unittest import TestCase, mock, main


class A:
__user_id = 3

def __init__(self, user, group):
"""
Your logic is missing - obviously
:param user:
:param group:
"""


def __get_group_members(self):
"""
Your logic is missing - obviously
:return:
"""
return ['user_1', 'user_2']

def is_member_of(self, group_name):
members = self.__get_group_members(group_name)

# will return if the user is a member of the group
return self.__user_id in members


class GroupTest(TestCase):
group_data = [1, 2]
user_id = 'test_user_id'

@mock.patch.object(A, '_A__get_group_members')
@mock.patch.object(A, '_A__user_id', new_callable=mock.PropertyMock)
def test_this_is_my_first_success(self, user_id_mock: mock.PropertyMock, get_group_members_mock: mock.MagicMock):
get_group_members_mock.return_value = self.group_data
user_id_mock.return_value = 3

x = A('user_3', 'this_group')
self.assertEqual(False, x.is_member_of('test_group'))

@mock.patch.object(A, '_A__get_group_members')
@mock.patch.object(A, '_A__user_id', new_callable=mock.PropertyMock)
def test_this_is_my_first_failure(self, user_id_mock: mock.PropertyMock, get_group_members_mock: mock.MagicMock):
get_group_members_mock.return_value = self.group_data
user_id_mock.return_value = 1

x = A('user_1', 'this_group')
self.assertEqual(True, x.is_member_of('test_group'))


if __name__ == '__main__':
main()

如果您知道您将在所有测试用例中模拟这两个属性,您可以在类级别添加装饰器并期待类似的参数。

如果属性是通过 __init__ 或任何其他方法设置的,您可以简单地更改它,如下所示。

from unittest import TestCase, mock, main


class A:
def __init__(self, user, group):
"""
Your logic is missing - obviously
:param user:
:param group:
"""


def __get_group_members(self):
"""
Your logic is missing - obviously
:return:
"""
return ['user_1', 'user_2']

def is_member_of(self, group_name):
members = self.__get_group_members(group_name)

# will return if the user is a member of the group
return self.__user_id in members


class GroupTest(TestCase):
group_data = [1, 2]
user_id = 'test_user_id'

@mock.patch.object(A, '_A__get_group_members')
def test_this_is_my_first_success(self, get_group_members_mock: mock.MagicMock):
x = A('user_3', 'this_group')

x._A__user_id = 5
get_group_members_mock.return_value = self.group_data

self.assertEqual(False, x.is_member_of('test_group'))

@mock.patch.object(A, '_A__get_group_members')
def test_this_is_my_first_failure(self, get_group_members_mock: mock.MagicMock):
get_group_members_mock.return_value = self.group_data

x = A('user_1', 'this_group')
x._A__user_id = 1
self.assertEqual(True, x.is_member_of('test_group'))


if __name__ == '__main__':
main()

关于python - 如何正确模拟类(class)的私有(private)成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55512708/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com