我一直在努力弄清楚如何模拟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
方法,还是我做了一些可怕的错误?
答案 0 :(得分:6)
我会采用修补模块中导入的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'))
答案 1 :(得分:2)
我找到了一种在我的测试中模拟sqlite3.Cursor的方法:
cursor = MagicMock(Cursor)
cursor.fetchall.return_value = [{'column1': 'hello', 'column2': 'world'}]
我在python中很新,但这就是我用Java做的。
答案 2 :(得分:-3)
你无法模拟一切,数据库特别棘手。我经常发现正确的事情(尤其是Sqlite,因为它很容易)是用模拟数据加载测试数据库并在测试中使用它(即灯具)。毕竟,您真正需要测试的是您的代码是否正在访问并正确查询数据库。
在这样的测试中,你经常试图回答的问题是“如果数据库中有X数据,我执行查询Y,该查询是否像我期望的那样返回Z”,或者更高级别“如果我将参数X传递给我的方法,它是否返回值Z(基于从数据库中获取Y)。“
在您的示例中,真正的问题是“SELECT * FROM foo where name = ?
在此方法中是否是正确的查询?”但如果你嘲笑回应,你就不回答。