28

csv ファイルを開き、ヘッダーと値の関連付けを設定するソース コードがあります。ソースコードを以下に示します。

def ParseCsvFile(source): 
  """Parse the csv file. 
  Args: 
    source: file to be parsed

  Returns: the list of dictionary entities; each dictionary contains
             attribute to value mapping or its equivalent. 
  """ 
  global rack_file 
  rack_type_file = None 
  try: 
    rack_file = source 
    rack_type_file = open(rack_file)  # Need to mock this line.
    headers = rack_type_file.readline().split(',') 
    length = len(headers) 
    reader = csv.reader(rack_type_file, delimiter=',') 
    attributes_list=[] # list of dictionaries. 
    for line in reader: 
      # More process to happeng. Converting the rack name to sequence. 
      attributes_list.append(dict((headers[i],
                                   line[i]) for i in range(length))) 
    return attributes_list 
  except IOError, (errno, strerror): 
    logging.error("I/O error(%s): %s" % (errno, strerror)) 
  except IndexError, (errno, strerror): 
    logging.error('Index Error(%s), %s' %(errno, strerror)) 
  finally: 
    rack_type_file.close() 

次のステートメントを嘲笑しようとしています

rack_type_file = open(rack_file) 

open(...) 関数をモックするにはどうすればよいですか?

4

8 に答える 8

28

これは確かに古い質問であるため、一部の回答は古くなっています。

mockライブラリの現在のバージョンには、まさにこの目的のために設計された便利な関数があります。仕組みは次のとおりです。

>>> from mock import mock_open
>>> m = mock_open()
>>> with patch('__main__.open', m, create=True):
...     with open('foo', 'w') as h:
...         h.write('some stuff')
...
>>> m.mock_calls
[call('foo', 'w'),
 call().__enter__(),
 call().write('some stuff'),
 call().__exit__(None, None, None)]
>>> m.assert_called_once_with('foo', 'w')
>>> handle = m()
>>> handle.write.assert_called_once_with('some stuff')

ドキュメントはこちらです。

于 2013-10-29T15:48:42.320 に答える
13

組み込み関数 open を mox use__builtin__モジュールでモックするには:

import __builtin__ # unlike __builtins__ this must be imported
m = mox.Mox()
m.StubOutWithMock(__builtin__, 'open')
open('ftphelp.yml', 'rb').AndReturn(StringIO("fake file content"))     
m.ReplayAll()
# call the code you want to test that calls `open`
m.VerifyAll()
m.UnsetStubs()

__builtins__常にモジュールであるとは限らないことに注意してください。タイプは dict である可能性があり__builtin__ます。システムの組み込みメソッドを参照するには、(「s」なしで) module を使用してください。

__builtin__モジュール詳細: http://docs.python.org/library/builtin .html

于 2011-06-11T14:20:10.583 に答える
3

私はあなたのサンプル関数を自由に書き直しました:

関数が次の名前のファイルにあるとします。code.py

# code.py
import csv

import logging


def ParseCsvFile(source):
    """Parse the csv file.
    Args:
      source: file to be parsed

    Returns: the list of dictionary entities; each dictionary contains
               attribute to value mapping or its equivalent.
    """
    global rack_file
    rack_file = source
    attributes_list = []

    try:
        rack_type_file = open(rack_file)
    except IOError, (errno, strerror):
        logging.error("I/O error(%s): %s", errno, strerror)
    else:
        reader = csv.DictReader(rack_type_file, delimiter=',')
        attributes_list = [line for line in reader]   # list of dictionaries
        rack_type_file.close()

    return attributes_list

簡単なテスト ケースは次のようになります。

# your test file
import __builtin__
import unittest
import contextlib
from StringIO import StringIO

import mox

import code


@contextlib.contextmanager
def mox_replayer(mox_instance):
    mox_instance.ReplayAll()
    yield
    mox_instance.VerifyAll()


class TestParseCSVFile(unittest.TestCase):

    def setUp(self):
        self.mox = mox.Mox()

    def tearDown(self):
        self.mox.UnsetStubs()

    def test_parse_csv_file_returns_list_of_dicts(self):
        TEST_FILE_NAME = 'foo.csv'

        self.mox.StubOutWithMock(__builtin__, 'open')
        open(TEST_FILE_NAME).AndReturn(StringIO("name,age\nfoo,13"))

        with mox_replayer(self.mox):
            result = code.ParseCsvFile(TEST_FILE_NAME)

        self.assertEqual(result, [{'age': '13', 'name': 'foo'}])  # works!


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

編集:

% /usr/bin/python2.6
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import __builtin__
>>> import mox
>>> mock = mox.Mox()
>>> mock.StubOutWithMock(__builtin__, 'open')
>>> mock.UnsetStubs()

mox 0.53を使用して2.6で正常に動作します

于 2011-03-08T23:43:45.207 に答える
2

こんにちは私は同様の問題を抱えていて、異なるモッキングライブラリ間をめくって髪を引き裂いていました。私はついに私が満足している解決策を見つけました、そして多分それはあなたを助けるかもしれませんか?最後に、私はMockerライブラリhttp://labix.org/mockerを使用しました。これは、モックオープンのコードです。

from mocker import Mocker
from StringIO import StringIO
import __builtin__
mocker = Mocker()
sourceFile = 'myTestFile.txt'
__builtin__.open = mocker.mock()
__builtin__.open(sourceFile)
mocker.result(StringIO('this,is,a,test,file'))

<the rest of your test setup goes here>

mocker.replay()

ParseCsvFile(sourceFile)

mocker.restore()
mocker.verify()

ちなみに、私がMockerを使用した理由は、openを使用してファイルを読み取り、次にopenを再度使用して同じファイルを新しいデータで上書きする関数をテストしていたためです。私ができる必要があるのは、最初のファイルが存在しない場合をテストすることでした。そのため、最初にIOErrorをスローし、次に2回目に動作するモックを設定しました。次のような設定:

from mocker import Mocker
import __builtin__

mocker = Mocker()

mockFileObject = mocker.mock()
__builtin__.open = mocker.mock()

__builtin__.open('previousState.pkl', 'r') 
mocker.throw(IOError('Boom'))

__builtin__.open('previousState.pkl','w') 
mocker.result(mockFileObject)

<rest of test setup >

mocker.replay()

<test>

mocker.restore() #required to restore the open method
mocker.verify()

お役に立てれば!

于 2012-01-11T09:22:24.520 に答える
0
>>> class A(object):
...     def __init__(self):
...         self.x = open('test.py')
... 
>>> old_open = open
>>> def open(s):
...     return "test\n"
... 
>>> a = A()
>>> a.x
'test\n'
>>> open = old_open
>>> a = A()
>>> a.x
<open file 'test.py', mode 'r' at 0xb7736230>
于 2011-03-08T22:46:39.430 に答える