根据pyodbc进行的SQL查询,对函数进行正确单元测试的pythonic方法是什么?据我所知,最好的方法是模拟从SQL服务器返回输出的函数。问题是模拟应该返回什么?
我的设置: 在lib1中:
def selectSQL(connection, query):
cursor = connection.cursor()
cursor.execute(query)
return cursor.fetchall()
在lib2中:
def function_to_be_tested(cxnx):
my_query = "SELECT r1, r2 FROM t1"
rows = lib1.selectSQL(cxnx, my_query)
# do someting with the rows like:
a = 0
for row in rows
a += row.r1 * row.r2
return a
我来了以下的解决方案:
,
out_tuple = namedtuple('out1', ["r1", "r2"])
printed_data = [(1,2),(2,3)]
out = [out_tuple(*row) for row in printed_data]
def test_mockSelectSQL(self):
piotrSQL.selectSQL = MagicMock()
piotrSQL.selectSQL.side_effect = [out]
self.assertEqual(lib2.function_to_be_tested(True), 7)
我唯一担心的是,mock返回的是namedtuple而不是像原始函数一样的pyodbc.Row。我检查了以下网站,以搜索有关如何正确创建pyodbc.Row的信息:
在pyodbc的unittest中没有if的构造函数 - 我没有在源代码中找到它(但我是新手所以我可能已经省略了它)...但是我在Row文档中找到了以下信息:
然而,有一些pyodbc添加使它们非常方便:
可以按列名访问值。
即使在光标关闭后也可以访问Cursor.description值。
可以替换值。
来自同一选择语句的行共享内存。
因此,它确实指出,namedtuple实际上与pyodbc.Row的行为方式相同(当涉及访问值时)。是否有更pythonic方式在pyodbc.Row上进行单元测试?可以假设这是一个很好的模拟?
答案 0 :(得分:1)
除了来自@Nullman对该问题的评论的建议之外,如果您想使用内存数据库,您可以尝试使用SQLite ODBC驱动程序,这样您就可以返回实际的pyodbc.Row
对象,如下所示: / p>
import pyodbc
conn_str = 'Driver=SQLite3 ODBC Driver;Database=:memory:'
cnxn = pyodbc.connect(conn_str, autocommit=True)
crsr = cnxn.cursor()
# create test data
crsr.execute("CREATE TABLE table1 (id INTEGER PRIMARY KEY, dtm DATETIME)")
crsr.execute("INSERT INTO table1 (dtm) VALUES ('2017-07-26 08:08:08')")
# test retrieval
crsr.execute("SELECT * FROM table1")
print(crsr.fetchall())
# prints:
# [(1, datetime.datetime(2017, 7, 26, 8, 8, 8))]
crsr.close()
cnxn.close()
我刚试过它,它在Windows上的PyCharm中为我工作。