2011-11-17 20 views
13

mockライブラリを使用して、open()によって返されたオブジェクトを反復するコードを模倣してテストするのに適した方法はどれですか?ファイルオブジェクトやPythonのイテラブルを模擬する

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でこれらを実行してきました、しかし、これらの同じアプローチは、同様のunittestで動作します。

関連する問題