简体   繁体   中英

How to mock the open function for unit test

I've got two files:

REF_FILE : it's a file with changing data

TEST_FILE: it's a file with fixed data (It's simply a REF_FILE at a given moment)

Now I want to test this function:

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)

The problem is the 'REF_FILE' is changing often so I can't properly test it. So i need to use 'TEST_FILE' and for that purpose I need to mock my open function. I can't find out how to mock it and I would like some help to figure out how to properly mock it in order to make it return my 'TEST_FILE'

I would recommend rewriting the function so it accepts file-like object (it would be easier to test and maintain ).

However if you can not, try this context-manager:

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
    ...

The context manager replaces (within with statement block) built-in function referenced by global label open with itself. Every call to open() in the body of the with block is a call of the __call__() method, which ignores all its arguments and returns opened TEST_FILE .

It is not the best possible implementation, since:

  1. it uses actual file, slowing your tests - a file-like object should be returned instead,
  2. it is not configurable - a file name (or content) should be given to its constructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM