2015-01-08 14 views
15

タイトルは単に私の問題を説明しました。 "_func_inner_1"を特定の戻り値でモックしたいと思います。おかげでどんな:)テスト中のユニットテストのためのモックフレームワークを使用してトルネードコルーチン関数をモックする方法は?

コード助言のために:

from tornado.gen import coroutine, Return 
from tornado.testing import gen_test 
from tornado.testing import AsyncTestCase 

import mock 

@coroutine 
def _func_inner_1(): 
    raise Return(1) 

@coroutine 
def _func_under_test_1(): 
    temp = yield _func_inner_1() 
    raise Return(temp + 1) 

をしかし、この直感的な解決策以下のエラーで

class Test123(AsyncTestCase): 

    @gen_test 
    @mock.patch(__name__ + '._func_inner_1') 
    def test_1(self, mock_func_inner_1): 
     mock_func_inner_1.side_effect = Return(9) 
     result_1 = yield _func_inner_1() 
     print 'result_1', result_1 
     result = yield _func_under_test_1() 
     self.assertEqual(10, result, result) 

を動作しない、_func_inner_1が原因それだコルーチン自然

にパッチされていないようです
AssertionError: 2 

返されたモック関数にコルーチンを追加すると、

@gen_test 
@mock.patch(__name__ + '._func_inner_1') 
def test_1(self, mock_func_inner_1): 
    mock_func_inner_1.side_effect = Return(9) 
    mock_func_inner_1 = coroutine(mock_func_inner_1) 
    result_1 = yield _func_inner_1() 
    print 'result_1', result_1 
    result = yield _func_under_test_1() 
    self.assertEqual(10, result, result) 

エラーは次のようになります。

Traceback (most recent call last): 
    File "tornado/testing.py", line 118, in __call__ 
    result = self.orig_method(*args, **kwargs) 
    File "tornado/testing.py", line 494, in post_coroutine 
    timeout=timeout) 
    File "tornado/ioloop.py", line 418, in run_sync 
    return future_cell[0].result() 
    File "tornado/concurrent.py", line 109, in result 
    raise_exc_info(self._exc_info) 
    File "tornado/gen.py", line 175, in wrapper 
    yielded = next(result) 
    File "coroutine_unit_test.py", line 39, in test_1 
    mock_func_inner_1 = coroutine(mock_func_inner_1) 
    File "tornado/gen.py", line 140, in coroutine 
    return _make_coroutine_wrapper(func, replace_callback=True) 
    File "tornado/gen.py", line 150, in _make_coroutine_wrapper 
    @functools.wraps(func) 
    File "functools.py", line 33, in update_wrapper 
    setattr(wrapper, attr, getattr(wrapped, attr)) 
    File "mock.py", line 660, in __getattr__ 
    raise AttributeError(name) 
AttributeError: __name__ 

@gen_test 
def test_4(self): 
    global _func_inner_1 
    mock_func_inner_1 = mock.create_autospec(_func_inner_1) 
    mock_func_inner_1.side_effect = Return(100) 
    mock_func_inner_1 = coroutine(mock_func_inner_1) 
    _func_inner_1 = mock_func_inner_1 
    result = yield _func_under_test_1() 
    self.assertEqual(101, result, result) 

答えて

22
を何パッチとは違って、これは私が見つけることができる最も近いソリューションですが、モック機能は、テストケースの実行後にリセットされません

ここには2つの問題があります:

最初は@mock.patch a nd @gen_test。 gen_testは、ジェネレータを「通常の」関数に変換することによって動作します。 mock.patchは通常の関数でのみ動作します(デコレータが伝える限り、ジェネレータは最初のyieldに到達するとすぐに戻ります。したがって、mock.patchはすべての作業を元に戻します)。この問題を回避するには、デコレータの順序を変更するか(常に@gen_test@mock.patchを入れて、またはその代わりにデコレータ形式のmock.patchwithフォームを使用。

第二には、コルーチンは例外を発生させてはいけません。その代わりに、彼らは返しますFutureには、結果または例外が含まれます。特別なReturn例外は、コルーチンシステムによってカプセル化されているため、未来からそれを発生させることはありません。例外で発生させるためにside_effectを使用する代わりに。

完全な解決策i s:

from tornado.concurrent import Future 
from tornado.gen import coroutine, Return 
from tornado.testing import gen_test 
from tornado.testing import AsyncTestCase 

import mock 

@coroutine 
def _func_inner_1(): 
    raise Return(1) 

@coroutine 
def _func_under_test_1(): 
    temp = yield _func_inner_1() 
    raise Return(temp + 1) 

class Test123(AsyncTestCase): 

    @mock.patch(__name__ + '._func_inner_1') 
    @gen_test 
    def test_1(self, mock_func_inner_1): 
     future_1 = Future() 
     future_1.set_result(9) 
     mock_func_inner_1.return_value = future_1 
     result_1 = yield _func_inner_1() 
     print 'result_1', result_1 
     result = yield _func_under_test_1() 
     self.assertEqual(10, result, result) 

import unittest 
unittest.main() 
+1

それは完璧に、素晴らしいおかげで動作します:) –

関連する問題