moxを使ってMySQLdbのテストを行う
ユニットテストを行う際に面倒なのが、外部のデータベースを利用している場合です。
ここではmoxというモックを使ってMySQLdbのテストを行なう方法を紹介します。
moxはpythonのモックライブラリの一種で、JavaのEasyMockを元にしています。
詳細はpymoxのページを見てもらうとして、ここではmoxを使った具体例を示します。
db1のtable1に対して「SELECT * FROM table1」というSQLを実行するプログラム
mymodel.pyを考えます。例えばtable1が
key | value |
---|---|
key1 | value1 |
keu2 | value2 |
という構造になっている場合、下記のkey, valueペアを返します。
(('key1', 'value1'), ('key2', 'value2'))
ここで外部のデータベースが行うことは、
- 「SELECT * FROM table1」というSQLを受け取る
- key, valueのペアを返す
の2つです。test_mymodel.pyの
self.cursor.execute("SELECT * FROM table1") self.cursor.fetchall().AndReturn((('key1', 'value1'), ('key2', 'value2')),)
がこの2つの機能を実装しています。
mymodel.py
# -*- coding: utf-8 -*- import MySQLdb def select(): con = MySQLdb.connect(host = '127.0.0.1', db = 'db1', user = 'user1', passwd = 'password1',) cursor = con.cursor() query = "SELECT * FROM table1" cursor.execute(query) res = cursor.fetchall() return res if __name__ == "__main__": select()
test_mymodel.py
# -*- coding: utf-8 -*- import mymodel import MySQLdb import MySQLdb.cursors import mox class Test(): def setUp(self): self.mox = mox.Mox() self.cursor = self.mox.CreateMock(MySQLdb.cursors.Cursor) self.con = self.mox.CreateMockAnything() def tearDown(self): self.mox.UnsetStubs() def test_select(self): self.mox.StubOutWithMock(MySQLdb, 'connect') MySQLdb.connect(host = mox.IsA(str), db = mox.IsA(str), user = mox.IsA(str), passwd = mox.IsA(str),).AndReturn(self.con) self.con.cursor().AndReturn(self.cursor) self.cursor.execute("SELECT * FROM table1") self.cursor.fetchall().AndReturn((('key1', 'value1'), ('key2', 'value2')),) self.mox.ReplayAll() res = mymodel.select() assert res == (('key1', 'value1'), ('key2', 'value2')) self.mox.VerifyAll() if __name__ == "__main__": t = Test() t.test_select()