Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何模拟sqlite3.Cursor_Python_Unit Testing_Sqlite_Mocking_Nose - Fatal编程技术网

Python 如何模拟sqlite3.Cursor

Python 如何模拟sqlite3.Cursor,python,unit-testing,sqlite,mocking,nose,Python,Unit Testing,Sqlite,Mocking,Nose,我一直在绞尽脑汁想弄清楚如何模拟sqlite3.Cursor类,特别是fetchall方法 考虑下面的代码示例 import sqlite3 from mock import Mock, patch from nose.tools import assert_false class Foo: def check_name(name): conn = sqlite3.connect('temp.db') c = conn.cursor()

我一直在绞尽脑汁想弄清楚如何模拟
sqlite3.Cursor
类,特别是
fetchall
方法

考虑下面的代码示例

import sqlite3

from mock import Mock, patch
from nose.tools import assert_false


class Foo:
    def check_name(name):
        conn = sqlite3.connect('temp.db')
        c = conn.cursor()
        c.execute('SELECT * FROM foo where name = ?', name)
        if len(c.fetchall()) > 0:
            return True
        return False


@patch('sqlite3.Cursor.fetchall', Mock(return_value=['John', 'Bob']))
def test_foo():
    foo = Foo()
    assert_false(foo.check_name('Cane'))
运行
nosetests
不会导致有趣的错误

E
======================================================================
ERROR: temp.test_foo
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/koddsson/.virtualenvs/temp/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/koddsson/.virtualenvs/temp/lib/python2.7/site-packages/mock.py", line 1214, in patched
    patching.__exit__(*exc_info)
  File "/home/koddsson/.virtualenvs/temp/lib/python2.7/site-packages/mock.py", line 1379, in __exit__
    setattr(self.target, self.attribute, self.temp_original)
TypeError: can't set attributes of built-in/extension type 'sqlite3.Cursor'

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (errors=1)

我是不能模仿
fetchall
方法,还是我做错了什么可怕的事?

你不能模仿所有的东西,数据库尤其棘手。我经常发现正确的做法(特别是使用Sqlite,因为它非常简单)是用模拟数据加载测试数据库,并在测试中使用它(即fixture)。毕竟,您真正需要测试的是您的代码是否正确地访问和查询数据库

在这样的测试中,您通常试图回答的问题是“如果数据库中有X个数据,并且我执行查询Y,那么该查询是否会像我预期的那样返回Z”,或者在更高的级别上“如果我将参数X传递给我的方法,它是否会返回值Z(基于从数据库中获取Y)。”


在您的示例中,真正的问题是“SELECT*FROM foo where name=?此方法中的查询是否正确?”但如果您模拟响应,则不会回答该问题。

我将采用修补模块中导入的sqlite3的方法,然后从那里开始工作

假设您的模块名为
what.py

我会修补掉
what.sqlite3
,然后模拟
.connect().cursor().fetchall的返回值

下面是一个更完整的示例:

from mock import patch
from nose.tools import assert_true, assert_false

from what import Foo

def test_existing_name():
    with patch('what.sqlite3') as mocksql:
        mocksql.connect().cursor().fetchall.return_value = ['John', 'Bob']
        foo = Foo()
        assert_true(foo.check_name('John'))

我找到了在测试中模拟sqlite3.Cursor的方法:

cursor = MagicMock(Cursor)
cursor.fetchall.return_value = [{'column1': 'hello', 'column2': 'world'}]

我对python非常陌生,但我在Java中就是这样做的。

See@JanneKarila我试过了,但现在我得到了一个断言。错误:我认为您的修补级别不对。就我个人而言,我会修补sqlite3本身并嘲笑fetch_all方法,就像这样:Alex,你应该公开要点作为答案,它对我很有效,thanks@RogerVeciana完成。:)