2017-04-12 67 views
0

我試圖測試一個Python方法包含with語句。 with聲明中的代碼可以引發RuntimeError。我正在談論的測試是否提高了RuntimeErrorTestCase - 異常不會引發與嘲笑__enter__

__enter____exit__方法很重(通常是打開和關閉SSH連接),我在測試時嘲笑它們。

這裏是方法的簡化定義欲測試:

# client.py 
class Client(): 
    def method_to_test(): 
     with self: 
      raise RuntimeError() 

爲了清楚的目的,我省略__enter____exit__的定義,併除去所有在method_to_test其中未參與的代碼當前的問題。

爲了測試這個方法,我嘲笑__enter____exit__,並檢查是否RuntimeError提高:

# tests.py 
from django.test import TestCase 
import mock 
from .client import Client 

class ClientTestCase(TestCase): 
    @mock.patch('mymodule.client.Client.__enter__') 
    @mock.patch('mymodule.client.Client.__exit__') 
    def test_method_raises_Runtime(self, mock_exit, mock_enter): 
     mock_enter.return_value = None 
     client = Client() 
     with self.assertRaises(RuntimeError): 
      client.method_to_test() 

此測試失敗:AssertionError: RuntimeError not raised

如果我不嘲笑__enter__,該RuntimeError升高。爲什麼嘲笑__enter__會使這個測試失敗?

+0

什麼是'mymodule'?我不認爲你嘲笑正確的事情。 – chepner

+0

@chepner mymodule是client.py和tests.py所在的模塊。當使用pdb時,我清楚地看到'self .__ enter__'和'self .__ exit__'類型是MagicMock,這意味着我在正確的位置上打補丁。 – Dunatotatos

回答

0

在PEP343 https://www.python.org/dev/peps/pep-0343/

The exception is swallowed if exit() returns true 

視爲self.__exit__是在Client.method_to_testMagicMock一個,self.__exit__返回MagicMock,評價爲True。吞嚥了RuntimeError

修復很簡單。 self.__exit__()作爲返回None代替MagicMock

# tests.py 
from django.test import TestCase 
import mock 
from .client import Client 

class ClientTestCase(TestCase): 
    @mock.patch('mymodule.client.Client.__enter__') 
    @mock.patch('mymodule.client.Client.__exit__') 
    def test_method_raises_Runtime(self, mock_exit, mock_enter): 
     # __exit__ returns None, evaluated as False 
     mock_exit.return_value = None 
     mock_enter.return_value = None 
     client = Client() 
     with self.assertRaises(RuntimeError): 
      client.method_to_test()