0

I have function that looks like this:

def create_json_file(directory):                                           
json_path = os.path.join(directory, 'myfile.json')                          
if os.path.exists(json_path):                                              
    return                                                                  
                                                                            
log_path = os.path.join(directory, 'data.txt')                               
if not os.path.exists(log_path):                                            
    return                                                                  
                                                                            
date = {"created_at": "value_from_data.txt"}
with open("myfile.json", "w") as f:                                          
    json.dump(date, f)

And I need to create a unittest that uses mock files.

The 3 Unittests that I need are:

  1. A mock myfile.json file where I will assert that the function will return None (based on the 1st if statement, since the file exists)
  2. A way to mock-hide the data.txt item in order to assert that the function will return None (based on the second if statement)
  3. A mock myfile.json file where I write the required data and then assert that the return matches the expected outcome.

So far I've tried tests 1. and 2. with variations of this but I've been unsuccessful:

class TestAdminJsonCreation(unittest.TestCase):                                 
    @patch('os.path.exists', return_value=True)                                                    
    def test_existing_admin_json(self):                                         
        self.assertNone(postprocess_results.create_json_file())  

I've also read about other solutions such as: Python testing: using a fake file with mock & io.StringIO But I haven't found a way to successfully do what I need...

Oluevaera
  • 3
  • 3

1 Answers1

1

You want to be able to provide different return values for each call to os.path.exists. Since you know the order of the calls, you can use side_effects to supply a list of values to be used in order.

class TestAdminJsonCreation(unittest.TestCase): 

    # No JSON file                                
    @patch('os.path.exists', return_value=True)                                                    
    def test_existing_admin_json(self):                                         
        self.assertNone(postprocess_results.create_json_file())

    # JSON file, log file                                
    @patch('os.path.exists', side_effects=[True, False])                                                    
    def test_existing_admin_json(self):                                         
        self.assertNone(postprocess_results.create_json_file())

    # JSON file, no log file
    @patch('os.path.exists', side_effects=[True, True])                                                    
    def test_existing_admin_json(self):                                         
        ...

The third test requires an actual file system, or for you to mock open.

chepner
  • 446,329
  • 63
  • 468
  • 610