2016-02-02 172 views
6

私はPython2で、このコードセグメントがあります。psycopg2カーソルオブジェクトをモックする方法は?

def super_cool_method(): 
    con = psycopg2.connect(**connection_stuff) 
    cur = con.cursor(cursor_factory=DictCursor) 
    cur.execute("Super duper SQL query") 
    rows = cur.fetchall() 

    for row in rows: 
     # do some data manipulation on row 
    return rows 

私はいくつかのユニットテストを書きたいと思います。私はどのようにmock.patchを使用してカーソルと接続変数を修正して、偽のデータセットを返すのか疑問に思っていますか? 、カーソルがcon.cursorの戻り値であるので

TypeError: can't set attributes of built-in/extension type 'psycopg2.extensions.cursor' 

答えて

4

:私は私のユニットテストのためではなく、無駄に次のコードセグメントを試してみた:

@mock.patch("psycopg2.connect") 
@mock.patch("psycopg2.extensions.cursor.fetchall") 
def test_super_awesome_stuff(self, a, b): 
    testing = super_cool_method() 

しかし、私は次のエラーを取得するように見えます接続を模擬し、それを正しく設定するだけで済みます。たとえば、

query_result = [("field1a", "field2a"), ("field1b", "field2b")] 
with mock.patch('psycopg2.connect') as mock_connect: 
    mock_connect.cursor.return_value.execute.fetch_all = query_result 
    super_cool_method() 
+0

これは私のために働いていません。 fetchallから返った結果は、 '' –

+0

@AllenLinです。ちょうど '実行する'。 – chepner

+0

cursor.executeは通常Noneを返します。なぜあなたは実行のための戻り値を設定しますが、フェッチしないのですか? –

13

一連の連鎖呼び出しがあり、それぞれが新しいオブジェクトを返します。あなたがのための参照を握るので

@mock.patch("psycopg2.connect") 
def test_super_awesome_stuff(self, mock_connect): 
    expected = [['fake', 'row', 1], ['fake', 'row' 2]] 

    mock_con = mock_connect.return_value # result of psycopg2.connect(**connection_stuff) 
    mock_cur = mock_con.cursor.return_value # result of con.cursor(cursor_factory=DictCursor) 
    mock_cur.fetchall.return_value = expected # return this when calling cur.fetchall() 

    result = super_cool_method() 
    self.assertEqual(result, expected) 

:あなたはだけpsycopg2.connect()コールを模擬した場合は、このような呼び出しのために返されたモックを参照.return_value属性を経由して通話の鎖(それぞれがモックオブジェクトを生成する)に従うことができます彼らは正しく呼び出された場合にはモックconnect機能だけでなく、モック接続とカーソルを使用すると、その後も主張できるオブジェクト:あなたはこれらをテストする必要がない場合

mock_connect.assert_called_with(**connection_stuff) 
mock_con.cursor.called_with(cursor_factory=DictCursor) 
mock_cur.execute.called_with("Super duper SQL query") 

、あなただけにreturn_value参照をチェーンにできました真っ直ぐ進んで下さい接続のオブジェクトのcursor()の結果に:

@mock.patch("psycopg2.connect") 
def test_super_awesome_stuff(self, mock_connect): 
    expected = [['fake', 'row', 1], ['fake', 'row' 2]] 
    mock_connect.return_value.cursor.return_value.fetchall.return_value = expected 

    result = super_cool_method() 
    self.assertEqual(result, expected) 
関連する問題