如何使用unittest模拟嵌套构造函数中的table.get_item调用?
解决DynamoDB get_item模拟失败的问题
你的测试失败核心原因是mock的目标路径不对,再加上测试代码里真实实例初始化和mock逻辑冲突。下面一步步帮你修正:
问题拆解
- 你现在mock的是
src.DBOps这个自定义类,但实际上需要模拟的是boto3创建的DynamoDB Table实例的get_item方法——毕竟你的业务类是调用boto3的资源来操作数据库的。 setUp里初始化了真实的dynamodbOps实例,这会触发真实的boto3资源初始化逻辑,和测试中的mock完全冲突,相当于一边模拟一边调用真实服务,肯定会失败。
修正方案
方案1:模拟boto3资源链(推荐)
我们从boto3的资源创建环节开始mock,让它返回预设的模拟Table实例:
import unittest from unittest import mock from src.DBOps import DBOps class test_GetDBItem(unittest.TestCase): @mock.patch('src.DBOps.boto3.resource') def test_run_query_with_item(self, mock_boto3_resource): # 1. 模拟Table实例的get_item方法返回值 mock_table = mock.Mock() mock_table.get_item.return_value = {"Blah": "Blah Blah"} # 2. 让boto3.resource返回的dynamodb实例,能得到我们模拟的Table mock_dynamodb = mock.Mock() mock_dynamodb.Table.return_value = mock_table mock_boto3_resource.return_value = mock_dynamodb # 3. 初始化业务类(此时用的都是模拟资源) db_table = "test_table" db_ops = DBOps() dyn = db_ops.dynamodbOps(db_table) # 4. 执行测试并验证 pool = 'some_pool' response = dyn.GetDBItem(pool) mock_table.get_item.assert_called_once_with(Key={'pool': pool}) self.assertEqual(response, {"Blah": "Blah Blah"})
方案2:直接mock目标方法
如果想更精准地mock table.get_item,可以指定正确的mock路径(路径要和被测试代码里的导入层级对应):
import unittest from unittest import mock from src.DBOps import DBOps class test_GetDBItem(unittest.TestCase): @mock.patch('src.DBOps.DBOps.dynamodbOps.table.get_item') def test_run_query_with_item(self, mock_get_item): mock_get_item.return_value = {"Blah": "Blah Blah"} # 初始化业务类 db_table = "test_table" db_ops = DBOps() dyn = db_ops.dynamodbOps(db_table) # 执行测试 pool = 'some_pool' response = dyn.GetDBItem(pool) # 验证调用 mock_get_item.assert_called_once_with(Key={'pool': pool}) self.assertEqual(response, {"Blah": "Blah Blah"})
额外必须修正的点
你的GetDBItem方法没有返回值!当前代码里response = self.table.get_item(...)后没有return response,所以测试中拿到的response会是None,记得在原业务代码里补充这一行:
def GetDBItem(self,pool): response = self.table.get_item(Key={'pool' : pool}) return response # 补充返回值,否则测试永远拿不到预期结果
内容的提问来源于stack exchange,提问作者Sagar Kadambi
相关产品推荐
相关产品推荐

