2013-12-12 4 views
5

Я вытаскиваю свои волосы, пытаясь понять, как издеваться над классом sqlite3.Cursor, в частности, с методом fetchall.Как я могу издеваться над sqlite3.Cursor

Рассмотрим следующий пример кода

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 или я делаю что-то ужасно неправильно?

+1

См. [В Python, как издеваться над классом расширения AC?] (Http://stackoverflow.com/q/17267587/222914) –

+1

@JanneKarila Я пробовал это, но теперь я получаю AssertionError https: // gist .github.com/anonymous/7931550: < –

+2

Я думаю, вы исправляете неправильный уровень. Лично я исправлял сам sqlite3 и высмеивал метод fetch_all следующим образом: https://gist.github.com/alexcouper/eec0d38454ce4bc43c6b –

ответ

4

Я хотел бы подходить к исправлению 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')) 
-3

Вы не можете издеваться над всем, и базы данных особенно сложны. Я часто считаю, что правильная вещь (особенно с Sqlite, так как это так просто) - загрузить тестовую базу данных с макетными данными и использовать ее в тестах (например, в приборах). В конце концов, то, что вам действительно нужно проверить, - это то, правильно ли ваш код обращается и правильно запрашивает базу данных.

Вопрос, на который вы обычно пытаетесь ответить в тесте, например: «Если в базе данных есть X-данные, и я выполняю запрос Y, этот запрос возвращает Z, как я ожидаю», или на более высоком уровне »If Я передаю параметр X моему методу, он возвращает значение Z (на основе получения Y из db). "

В вашем примере настоящий вопрос: «Есть ли SELECT * FROM foo where name = ? правильный запрос в этом методе?» но вы не отвечаете на него, если вы издеваетесь над ответом.

2

Я нашел способ издеваться sqlite3.Cursor в моих тестах:

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

Я довольно нового в Python, но это, как я сделайте это на Java.

Смежные вопросы