如何模拟单元测试的开放功能

How to mock the open function for unit test

我有两个文件:

REF_FILE : 这是一个有变化数据的文件

TEST_FILE: 是固定数据的文件(只是给定时刻的REF_FILE)

现在我要测试这个功能:

def get_info_from_extract(mpm):    
   fid = open(REF_FILE)
   all_infos = json.load(fid)
   fid.close()
   for m in all_infos:
      if m['mpm_id'] == mpm:
          break
   return m



class Test_info_magento(unittest.TestCase):
   def test_should_have_value(self):
      # GIVEN
      mpm=107
      expected_value = 1.345

      # WHEN
      #MOCK OPEN FUNCTION TO READ TEST_FILE
      m = file_info.get_info_from_extract(mpm)

      # THEN
      self.assertEqual(m['value'], expected_value)

问题是 'REF_FILE' 经常变化,所以我无法正确测试它。所以我需要使用 'TEST_FILE' 并且为此我需要模拟我的开放功能。我找不到如何模拟它,我想得到一些帮助来弄清楚如何正确地模拟它以使其 return 我的 'TEST_FILE'

我建议重写该函数,使其接受类文件对象(测试和维护会更容易)。

但是如果你不能,试试这个上下文管理器:

class MockOpen(object):
    def __call__(self, *args, **kwargs):
        #print('mocked')
        return self.__open(TEST_FILE) #it would be better to return a file-like object instead
    def __enter__(self):
        global open
        self.__open = open
        open = self
    def __exit__(self, exception_type, exception_value, traceback):
        global open
        open = self.__open

with MockOpen():
    # here you run your test
    ...

上下文管理器用自身替换(在with 语句块内)全局标签open 引用的内置函数。在 with 块的主体中​​对 open() 的每次调用都是对 __call__() 方法的调用,该方法忽略其所有参数并且 returns 打开 TEST_FILE.

这不是最好的实施方式,因为:

  1. 它使用实际文件,减慢您的测试 - 应该返回一个类似文件的对象,
  2. 它是不可配置的 - 应该给它的构造函数一个文件名(或内容)。