如何模拟单元测试的open函数

时间:2016-05-20 12:24:39

标签: python unit-testing mocking

我有两个文件:

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',为此我需要模拟我的open函数。我无法找到如何模拟它,我想帮助弄清楚如何正确模拟它以使其返回我的'TEST_FILE'

1 个答案:

答案 0 :(得分:1)

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

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

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__()方法的调用,该方法忽略其所有参数并返回打开的TEST_FILE

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

  1. 它使用实际文件,减慢了测试速度 - 应该返回类似文件的对象,
  2. 它不可配置 - 应该为其构造函数提供文件名(或内容)。