2011-11-17 5 views
13

mock 라이브러리를 사용하여 open()에 의해 반환 된 객체를 반복하는 코드를 조롱하고 테스트하는 데는 어느 방법이 적합합니까? 파이썬에서 파일 객체 또는 iterable 조롱하기

whitelist_data.py

: 나는 그것을 테스트하려고 방법

WHITELIST_FILE = "testdata.txt" 

format_str = lambda s: s.rstrip().lstrip('www.') 
whitelist = None 

with open(WHITELIST_FILE) as whitelist_data: 
    whitelist = set(format_str(line) for line in whitelist_data) 

if not whitelist: 
    raise RuntimeError("Can't read data from %s file" % WHITELIST_FILE) 

def is_whitelisted(substr): 
    return 1 if format_str(substr) in whitelist else 0 

가 여기에 있습니다. python tests.py

import unittest 
import mock 

TEST_DATA = """ 
domain1.com 
domain2.com 
domain3.com 
""" 

class TestCheckerFunctions(unittest.TestCase): 

    def test_is_whitelisted_method(self): 
     open_mock = mock.MagicMock() 
     with mock.patch('__builtin__.open',open_mock): 
      manager = open_mock.return_value.__enter__.return_value 
      manager.__iter__ = lambda s: iter(TEST_DATA.splitlines()) 
      from whitelist_data import is_whitelisted 
      self.assertTrue(is_whitelisted('domain1.com')) 

if __name__ == '__main__': 
    unittest.main() 

결과는 다음과 같습니다

$ python tests.py 

E 
====================================================================== 
ERROR: test_is_whitelisted_method (__main__.TestCheckerFunctions) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "tests.py", line 39, in test_is_whitelisted_method 
    from whitelist_data import is_whitelisted 
    File "/Users/supa/Devel/python/whitelist/whitelist_data.py", line 20, in <module> 
    whitelist = set(format_str(line) for line in whitelist_data) 
TypeError: 'Mock' object is not iterable 

---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

UPD : 아담, 내가 다시 설치 한 모의 라이브러리 (pip install -e hg+https://code.google.com/p/mock#egg=mock) 업데이트 tests.py에 감사합니다. 매력처럼 작동합니다.

답변

15

당신은 MagicMock을 찾고 있습니다. 이것은 반복을 지원합니다.

모의 0.80beta4에서 patchMagicMock을 반환합니다. 그래서이 간단한 예제는 작동 :

import mock 

def foo(): 
    for line in open('myfile'): 
     print line 

@mock.patch('__builtin__.open') 
def test_foo(open_mock): 
    foo() 
    assert open_mock.called 

당신이 (당신이처럼 보이는) 모의 0.7.x를 실행하는 경우, 당신이 혼자 패치와 함께이 작업을 수행 할 수 있다고 생각하지 않습니다. 그런 다음 패치에 전달할 별도로 모의을 만들어야합니다 :

import mock 

def foo(): 
    for line in open('myfile'): 
     print line 

def test_foo(): 
    open_mock = mock.MagicMock() 
    with mock.patch('__builtin__.open', open_mock): 
     foo() 
     assert open_mock.called 

주 - 나는 py.test 이러한를 실행했습니다, 그러나,이 같은 접근 방식뿐만 아니라 유닛 테스트 작동합니다.