2017-04-05 70 views
0

我想編寫一個單元測試,可以確保函數調用中的SQL語句是正確的。它應該測試這個調用的執行。然後,我想嘲笑調用提交,以便不會插入數據庫。我正在使用psycopg2進行測試。嘲笑一個類的一個功能

我有這樣一個功能:

def test_insert(a, b, c): 
    con = psycopg2.connect(os.environ['PGDB']) 
    cur = con.cursor() 
    cur.execute('insert into test_table values ({a}, {b}, {c})'.format(a=a, b=b, c=c)) 
    con.commit() 
    con.close() 

調用test_insert(1,2,3)當我看到插入到表中的行。現在我試圖嘲笑這個電話。到目前爲止,我採取了幾種方法:

@mock.patch('psycopg2.connect') 
def test(mock_connect, a, b, c): 
    mock_con = mock_connect.return_value 
    mock_con.commit.return_value = None 
    insert_row(a, b, c) 

這似乎工作,但實際上並沒有調用執行語句。 test_insert(1,4,'xyz')失敗,例如test(1,4,'xyz')沒有。接下來,我想嘲笑剛剛提交連接類的方法psycopg2:

@mock.patch('psycopg2.extensions.connection.commit') 
def test_insert(mock_commit, a, b, c): 
    mock_commit.return_value = None 
    insert_row(a,b,c) 

但是這給了我一個語法錯誤

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/home/a/.virtualenv/test/lib/python2.7/site-packages/mock/mock.py", line 1318, in patched 
    patching.__exit__(*exc_info) 
    File "/home/a/.virtualenv/test/lib/python2.7/site-packages/mock/mock.py", line 1480, in __exit__ 
    setattr(self.target, self.attribute, self.temp_original) 
TypeError: can't set attributes of built-in/extension type 'psycopg2.extensions.connection' 

有沒有做什麼,我試圖做一個好辦法?

回答

0

我假設您使用的是pytest,如果它們不是實際測試,那麼將其命名爲test_並不是一個好的做法,因爲這可能會引起測試框架的問題。因此,我稍微修改您的初始片斷如下,我命名爲模塊psyco.py

import psycopg2 
import os 

def insert(a, b, c): 
    con = psycopg2.connect(os.environ['PGDB']) 
    import ipdb; ipdb.set_trace() 
    cur = con.cursor() 
    cur.execute('insert into test_table values ({a}, {b}, {c})'.format(a=a, b=b, c=c)) 
    con.commit() 
    con.close() 

接下來,我考慮到how patch workswhere to patch創造了你的方法測試。正如你正在處理的環境變量this question可以幫助你理解爲什麼我這樣嘲笑它。

的示例性實現的測試可以如下:

from psyco import insert 
from unittest.mock import patch, Mock, MagicMock 
import os 

@patch.dict(os.environ,{'PGDB':'db_url'}) 
@patch('psycopg2.connect') 
def test_insert_function(psycopg2_mock): 

    x = 1 
    y = 4 
    z = 'xyz' 
    sql_query = 'insert into test_table values ({0}, {1}, {2})'.format(x,y,z) 
    insert(x,y,z) 
    assert psycopg2_mock.return_value.cursor.call_count == 1 
    psycopg2_mock.return_value.cursor.return_value.execute.assert_called_with(sql_query) 
    assert psycopg2_mock.return_value.commit.call_count == 1 
    assert psycopg2_mock.return_value.close.call_count == 1 
+0

提問者是不是要修補環境變量或'connect'。他們正在嘗試補丁'commit'。 – user2357112

+0

@ user2357112我得到yur點,我認爲,因爲它是一個單元測試你不想有外部依賴。這就是爲什麼我建議既要檢查「函數調用是否是正確的」,也要嘲笑調用提交,因爲'psycopg2.connect'調用是一個模擬 –