2015-01-08 13 views
15

Başlık sadece sorunumu açıkladı. "_func_inner_1" ile belirli bir dönüş değeri elde etmek istiyorum. ,Bir birim testi için sahte çerçeve kullanarak bir kasırga coroutine işlevi alay nasıl?

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) 

Fakat, bu sezgisel çözüm aşağıda hata ile

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) 

çalışmıyor _func_inner_1 o eşyordam doğa

var dolayı yamalı değil gibi görünüyor: Herhangi için teşekkürler

kodu test altında :) tavsiyede

Koroutini yama ekli sahte işlevine eklerseniz

@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) 

hata olur:

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__ 

Bu bulabilirim yakın çözüm, ancak alaycı fonksiyonu

@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) 

cevap

22
ne yama aksine test durumu yürütme sonra sıfırlanır ALINMAYACAKTIR

Burada iki sorun var:

İlk olarak @mock.patch arasındaki etkileşim ve @gen_test. gen_test, bir jeneratörü "normal" bir işleve dönüştürerek çalışır; mock.patch sadece normal fonksiyonlar üzerinde çalışır (dekoratörün anlayabildiği kadarıyla jeneratör ilk yield'a ulaşır ulaşmaz geri döner, böylece mock.patch tüm çalışmalarını geri alır). Bu sorunu önlemek için, dekoratörler yeniden düzenleyebilirsiniz ya (her zaman@gen_test önce @mock.patchkoymak veya onların yerine dekoratör formunun mock.patch ait with formu kullanın.

İkincisi, eşyordamlar bir istisna asla. Bunun yerine, dönmek Bir sonuç veya istisna içerecek bir Future.Özel Return istisnası, coroutine sistemi tarafından kapsüllenmiş, asla bir Gelecekten yükseltmeyeceksin.Ağaçlarınızı oluşturduğunuzda, uygun Geleceği yaratmanız ve dönüş değeri olarak ayarlamanız gerekir İstisnai yükseltmek için side_effect kullanmak yerine

Tam çözüm 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

mükemmel çalışıyor, harika teşekkürler :) –