2

I am writing a unit test for a function in my script, however I am having trouble creating a mock file. My function takes in a filename and output's it's md5 value.

def md5(file_name):
    #Function to return the md5 value of a file
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()

My unittest at the moment:

import mock
class Function_to_test_TestCase(unittest.TestCase):

    def test_filename(self):
        with mock.patch('__main__.open', mock.mock_open(read_data=''), create=True) as m:
            md5_value=my_script.function_to_get_md5_value(m)

However I get the error:

with open(fname, "rb") as f:
TypeError: coercing to Unicode: need string or buffer, MagicMock found

Is this way the correct way to make a mock file with a related mock md5 value? Any advice is appreciated!

Catherine
  • 689
  • 7
  • 26
  • Can you explain where is function my_script.function_to_get_md5_value(m) located ? If this is your md5 function, why do you call it with mock argument instead of filename? – Andrey Belyak May 10 '16 at 15:05
  • @AndreyBelyak Hi it's a function within a wider script that scans a directory of files and produces a manifest file containg each file name and md5 value. I am in the process of creating unit test for each function in my script, I was just wondering is there a way to create a simple file in a unittest scenario in order to test my function – Catherine May 10 '16 at 15:24
  • I think that the simplest way is to use real file with sample data. You can place it inside your test folder and add to vcs. – Andrey Belyak May 10 '16 at 15:58

1 Answers1

3

May be you should specify read_data as binary? Here is a working example, you can paste it to file and run with unittest:

import hashlib
from unittest import TestCase

import mock


def md5(file_name):
    hash_md5 = hashlib.md5()
    with open(file_name, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()


class MD5TestCase(TestCase):
    def test(self):
        with mock.patch('%s.open' % __name__, mock.mock_open(read_data=b'aaa'), create=True) as m:
            result = md5("lalala")
            self.assertEqual(result, '47bce5c74f589f4867dbd57e9ca9f808')

The answer is based on that answer: How do I mock an open used in a with statement (using the Mock framework in Python)?

Community
  • 1
  • 1
Andrey Belyak
  • 625
  • 8
  • 17
  • I seem to get the following error " with open(fname, "rb") as f: IOError: [Errno 2] No such file or directory: 'lalala' " if I use 'm' I get the error: " TypeError: coercing to Unicode: need string or buffer, MagicMock found " – Catherine May 11 '16 at 08:25
  • IOError means that open call is not patched correctly. Check mock.patch('XXX.open',... ) XXX should be module name with you function. – Andrey Belyak May 11 '16 at 09:35