在单元测试中模拟对象时使用真实数据
Using real data when mocking objects in unit test
我在一些单元测试中进行模拟,我想知道在模拟时是否可以或建议使用真实数据(我正在处理非敏感数据)。
例如,我在这里使用 azure 服务主体测试允许在应用程序中进行身份验证的用户成员:
def create_mock(status_code, data):
def mocked_requests(*args, **kwargs):
class MockResponse:
def __init__(self, status_code, json_data):
self.json_data = json_data
self.status_code = status_code
def json(self):
return self.json_data
return MockResponse(status_code, data)
return mocked_requests
class RolesTestCase(unittest.TestCase):
@mock.patch('requests.get',
side_effect=create_mock(
200,
# HERE MY OBJECT OR DATA MOCKED.
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals('99999')/appRoleAssignedTo",
"value": [{
"id": "99999",
"deletedDateTime": "null",
"appRoleId": "00000000-0000-0000-0000-000000000000",
"createdDateTime": "2021-03-21T17:15:40.516616Z",
"principalDisplayName": "Bernardo Garcia Loaiza",
"principalId": "99999",
"principalType": "User",
"resourceDisplayName": "my-service-principal-name",
"resourceId": "99999"
}]
}
)
)
@mock.patch('roles.get_sp_object_id')
def test_get_user_role_assignments(self, get_sp_object_id, mock):
token = "FOOBAR"
get_user_role_assignments(token, {"id": "123", "name": "group_name"})
get_sp_object_id.assert_called_with(token, {"id": "123", "name": "group_name"})
在上面的 @mock.patch('requests.get, ...'
代码部分,如果 JSON 文档中的 99999
值不是我输入的真实值,是否可以?
这个问题可能有点宽泛。但总的来说,你想做这样的事情:
在单元测试中,尝试确定所有 类 可能导致不同行为的输入,并用每个示例进行测试。例如,一个涉及平方根的函数应该用正数、0 和负数进行测试,以查看它在每种情况下的行为是否正确。如果您只使用您当前感兴趣的数据,您将拥有一个脆弱的系统。如果 (a) 您的软件处理的数据发生变化或 (b) 您的函数被另一个开发人员在另一个上下文中调用,那么您最终可能会得到一个通过测试但在生产中中断的函数。如果您想包含一个真实数据示例作为健全性检查,那为什么不呢。
在端到端测试和集成测试中,您通常需要使用真实记录。
但实际上它取决于很多因素:
你在使用测试驱动开发吗?
你在使用 CI/CD 吗?
你的测试覆盖率是多少?
你的预算是多少?
生产失败的成本是多少?
您对知道预期的数据类型有多大信心?
项目范围扩大或改变的可能性有多大?
测试甚至对功能有意义吗?
等等
我在一些单元测试中进行模拟,我想知道在模拟时是否可以或建议使用真实数据(我正在处理非敏感数据)。
例如,我在这里使用 azure 服务主体测试允许在应用程序中进行身份验证的用户成员:
def create_mock(status_code, data):
def mocked_requests(*args, **kwargs):
class MockResponse:
def __init__(self, status_code, json_data):
self.json_data = json_data
self.status_code = status_code
def json(self):
return self.json_data
return MockResponse(status_code, data)
return mocked_requests
class RolesTestCase(unittest.TestCase):
@mock.patch('requests.get',
side_effect=create_mock(
200,
# HERE MY OBJECT OR DATA MOCKED.
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals('99999')/appRoleAssignedTo",
"value": [{
"id": "99999",
"deletedDateTime": "null",
"appRoleId": "00000000-0000-0000-0000-000000000000",
"createdDateTime": "2021-03-21T17:15:40.516616Z",
"principalDisplayName": "Bernardo Garcia Loaiza",
"principalId": "99999",
"principalType": "User",
"resourceDisplayName": "my-service-principal-name",
"resourceId": "99999"
}]
}
)
)
@mock.patch('roles.get_sp_object_id')
def test_get_user_role_assignments(self, get_sp_object_id, mock):
token = "FOOBAR"
get_user_role_assignments(token, {"id": "123", "name": "group_name"})
get_sp_object_id.assert_called_with(token, {"id": "123", "name": "group_name"})
在上面的 @mock.patch('requests.get, ...'
代码部分,如果 JSON 文档中的 99999
值不是我输入的真实值,是否可以?
这个问题可能有点宽泛。但总的来说,你想做这样的事情:
在单元测试中,尝试确定所有 类 可能导致不同行为的输入,并用每个示例进行测试。例如,一个涉及平方根的函数应该用正数、0 和负数进行测试,以查看它在每种情况下的行为是否正确。如果您只使用您当前感兴趣的数据,您将拥有一个脆弱的系统。如果 (a) 您的软件处理的数据发生变化或 (b) 您的函数被另一个开发人员在另一个上下文中调用,那么您最终可能会得到一个通过测试但在生产中中断的函数。如果您想包含一个真实数据示例作为健全性检查,那为什么不呢。
在端到端测试和集成测试中,您通常需要使用真实记录。
但实际上它取决于很多因素: 你在使用测试驱动开发吗? 你在使用 CI/CD 吗? 你的测试覆盖率是多少? 你的预算是多少? 生产失败的成本是多少? 您对知道预期的数据类型有多大信心? 项目范围扩大或改变的可能性有多大? 测试甚至对功能有意义吗? 等等