Python3.3以降は標準でMockが使えるようだけど、Python2.7系では標準では入ってないのでインストールする。
$ pip install mock
サンプルコードは以下に。
# -*- coding:utf-8 -*- import unittest from mock import Mock, patch # DBにつなぐのでテストのときは使いたくないクラス class HogehogeDao(object): def __init__(self): pass def find(self, param_1, param_2): print('DBにつなぐよ') print('find ' + param_1 + param_2) # テストの対象となるクラス class CalculationModel(object): def __init__(self, dao): self.__dao = dao def execute(self): return self.__dao.find('hoge', param_2='foo') # 使い方 calc = CalculationModel(HogehogeDao()) calc.execute() # DBにつなぐよ # find hogefoo # と表示される。 # ------------------------------ ここからユニットテスト --------------------------# class SideEffectTestResult(object): """side_effectの返り値用 """ pass class CalculationModelTestCase(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def dataProvider(self, param_1, param_2): # 返り値を置き換える関数と同じ数の引数でないといけない。 return SideEffectTestResult() def test_execute_1(self): """Mockインスタンスに置き換えてのテスト """ mock_dao = Mock() # Mockの作成 # findメソッドとその返り値を作成 mock_dao.find.return_value = 'testtest' # テスト対象のインスタンスを作成 test_obj = CalculationModel(mock_dao) # 返り値が変わっていることを確認。 self.assertEqual('testtest', test_obj.execute()) # findメソッドが1回呼ばれていることを確認。 self.assertEqual(mock_dao.find.call_count, 1) # メソッドが呼ばれたときの引数を取得できる # 0番から呼ばれた順に格納されている # callオブジェクトに格納されるのでlist化 # 配列の0番目にタプルで引数、1番目に辞書でキーワード引数が格納される self.assertEqual(list(mock_dao.find.call_args_list[0]), [('hoge',), {'param_2': 'foo'}]) def test_execute_2(self): """メソッドをMockインスタンスに置き換えてのテスト """ HogehogeDao.find = Mock(return_value='method_mock_test') dao = HogehogeDao() test_obj = CalculationModel(dao) self.assertEqual('method_mock_test', test_obj.execute()) def test_execute_3(self): """with構文とpatch()を使って置き換えてのテスト """ with patch('__main__.HogehogeDao') as mock_dao: mock_dao.find.return_value = 'with_mock_test' test_obj = CalculationModel(mock_dao) self.assertEqual('with_mock_test', test_obj.execute()) def test_execute_4(self): """side_effectを使ってメソッドを返り値にする """ mock_dao = Mock() mock_dao.find.side_effect = self.dataProvider # テスト対象のインスタンスを作成 test_obj = CalculationModel(mock_dao) # 返り値が変わっていることを確認。 self.assertIsInstance(test_obj.execute(), SideEffectTestResult) unittest.main()
クラスをmock.Mock()で置き換えることができる。
クラスを置き換えるときは、メソッド名.return_valueで返り値を設定できる。 メソッド名.side_effectだと返り値を返す関数を設定することもできる。 そのときは元のメソッドと同じ数の引数をもたないといけない。
メソッドを置き換えるときも特に大きくは変わらない。
with構文で使うときはpatch()を使う。
そんなところで、わりと簡単にできるのでおすすめ。