Python 如何模拟数据库的方法

Python 如何模拟数据库的方法,python,database,unit-testing,mocking,Python,Database,Unit Testing,Mocking,我对python和mocking都是新手。因此,我试图通过阅读文档找到解决问题的方法: ,第条如下: 还有很多问题。但我还没找到解决办法 我尝试模拟两个函数,它们是创建数据库连接并将数据放入数据帧中。它们用于post函数(覆盖django post函数): 在测试环境中,get\u connection应不返回任何内容,fetch\u dataframe应返回之前定义的数据帧 我的测试类如下所示: class IndexViewTest(TestCase): @mock.patch('du_d

我对python和mocking都是新手。因此,我试图通过阅读文档找到解决问题的方法: ,第条如下: 还有很多问题。但我还没找到解决办法

我尝试模拟两个函数,它们是创建数据库连接并将数据放入数据帧中。它们用于post函数(覆盖django post函数):

在测试环境中,
get\u connection
应不返回任何内容,
fetch\u dataframe
应返回之前定义的数据帧

我的测试类如下所示:

class IndexViewTest(TestCase):

@mock.patch('du_db.db.get_connection')
@mock.patch('du_db.db.fetch_dataframe')
def setUp(self, mock_get_connection, mock_fetch_dataframe):
    self.c = Client()
    mock_get_connection = mock_get_connection()
    mock_fetch_dataframe = mock_fetch_dataframe()
    mock_get_connection.return_value = ""
    df = {'lot_of_data': ['xy', 'z'], 'more_data': [8, 9]}
    mock_fetch_dataframe.return_value = pd.DataFrame(df)
    assert mock_get_connection is data_utils.db.get_connection()
    assert mock_fetch_dataframe is data_utils.db.fetch_dataframe()
    assert mock_get_connection.called
    assert mock_get_connection.called

# Lot of test-functions similar to this:
def test_valid_data(self):
    resp = self.c.post('/', data={'id': 3338})
    self.assertEqual(resp.status_code, 200)
    self.assertContains(resp, 'Hello', status_code=200)
我收到以下错误消息:

通过mock替换原来的函数是行不通的

谢谢你的帮助

class IndexViewTest(TestCase):

    @mock.patch('du_db.db.get_connection')
    @mock.patch('du_db.db.fetch_dataframe')
    def setUp(self, mock_fetch_dataframe, mock_get_connection):
        self.c = Client()
        mock_get_connection = mock_get_connection() # remove this
        mock_fetch_dataframe = mock_fetch_dataframe() # remove this
当您调用上面的mock时,它们将返回另一个新的mock。通过指定相同的名称,将失去对修补过的模拟的引用。您将无法配置或检查它们

        mock_get_connection.return_value = "" # this is NOT the mock you think
                                              # unless removing lines above.
                                              # And so on...
        df = {'lot_of_data': ['xy', 'z'], 'more_data': [8, 9]}
        mock_fetch_dataframe.return_value = pd.DataFrame(df)

        # data__utils or du_db ??
        assert mock_get_connection is data_utils.db.get_connection()                                                                 
        assert mock_fetch_dataframe is data_utils.db.fetch_dataframe()
        assert mock_get_connection.called
        assert mock_get_connection.called

    # Lot of test-functions similar to this:
    def test_valid_data(self):
        resp = self.c.post('/', data={'id': 3338})
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, 'Hello', status_code=200)
编辑: 据我所知,你已经看到pdb的模拟在起作用。要使测试按您喜欢的方式工作,您需要对使用这两个函数的每个测试函数进行修补,例如修补程序装饰器。然后,您必须在修补测试函数中设置模拟。通常在测试中断言,但在设置中不断言。我知道您在这里只是为了方便,因为您对运行的代码有一些疑问

如果您正在考虑在设置中设置模拟以供其他测试函数使用(您不能这样做,您必须将它们存储在self中,然后在测试函数中再次管理它们),那么您可能对模拟文档中的此示例感兴趣:

管理修补程序的另一种方法是使用修补程序方法: 开始和停止。这些允许您将补丁移动到设置中 和拆卸方法


不幸的是,在删除这两行之后,我仍然得到相同的错误,我将断言更改为du_db。如果我设置pdb并查找
mock\u get\u连接
i get:。而另一种方式则围绕着fetch_数据帧。我以为是通过@mock命令建立的。patch@ediordna,函数首先接收内部修补程序。没有注意到顺序错误(现在已编辑)。@ediordna请参阅我的第二次编辑。我希望这可以帮助您将模拟设置移动到setUpHi progmatico,非常感谢您的帮助回答。我还没有真正理解整个python模拟背后的逻辑,但我找到了一种方法来成功模拟setUp()中的两个函数:
data\u utils.db.get\u connection=MagicMock(return\u value=“”)
data\u utils.db.fetch\u dataframe=MagicMock(return\u value=pd.dataframe(df))
@ediordna“…我还尝试了补丁()-是的,但找不到嘲笑的方法。”。这不是因为补丁字符串缺少包或模块部分吗?但即使这样,您也可以直接指定一个Mock。看见模仿init很奇怪,因为对象将存在(init不是构造函数),但您删除了对其属性的初始化,而且这也不能完全保证,因为某些对象属性可能仍然被分配到init之外。
        mock_get_connection.return_value = "" # this is NOT the mock you think
                                              # unless removing lines above.
                                              # And so on...
        df = {'lot_of_data': ['xy', 'z'], 'more_data': [8, 9]}
        mock_fetch_dataframe.return_value = pd.DataFrame(df)

        # data__utils or du_db ??
        assert mock_get_connection is data_utils.db.get_connection()                                                                 
        assert mock_fetch_dataframe is data_utils.db.fetch_dataframe()
        assert mock_get_connection.called
        assert mock_get_connection.called

    # Lot of test-functions similar to this:
    def test_valid_data(self):
        resp = self.c.post('/', data={'id': 3338})
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, 'Hello', status_code=200)
>>> class MyTest(TestCase):
    ...
    def setUp(self):
        ...
        self.patcher = patch(’mymodule.foo’)
        ...
        self.mock_foo = self.patcher.start()
    ...
    ...
    def test_foo(self):
        ...
        self.assertTrue(mymodule.foo is self.mock_foo)
        ...
        ...
    def tearDown(self):
        ...
        self.patcher.stop()
        ...
>>> MyTest(’test_foo’).run()