web-dev-qa-db-fra.com

Mock ensemble python

J'essaie de faire un test simple en python, mais je ne suis pas en mesure de comprendre comment accomplir le processus de simulation.

Voici le code de classe et def:

class FileRemoveOp(...)
    @apply_defaults
    def __init__(
            self,
            source_conn_keys,
            source_conn_id='conn_default',
            *args, **kwargs):
        super(v4FileRemoveOperator, self).__init__(*args, **kwargs)
        self.source_conn_keys = source_conn_keys
        self.source_conn_id = source_conn_id


    def execute (self, context)
          source_conn = Connection(conn_id)
          try:
              for source_conn_key in self.source_keys:
                  if not source_conn.check_for_key(source_conn_key):    
                      logging.info("The source key does not exist")  
                  source_conn.remove_file(source_conn_key,'')
          finally:
              logging.info("Remove operation successful.")

Et voici mon test pour la fonction d'exécution:

@mock.patch('main.Connection')
def test_remove_execute(self,MockConn):
    mock_coon = MockConn.return_value
    mock_coon.value = #I'm not sure what to put here#
    remove_operator = FileRemoveOp(...)
    remove_operator.execute(self)

Étant donné que la méthode execute essaie d'établir une connexion, je dois me moquer de cela, je ne veux pas établir une vraie connexion, il suffit de renvoyer quelque chose de faux. Comment puis-je faire ça? J'ai l'habitude de faire des tests en Java mais je n'ai jamais fait sur python ..

16
AnaF

Tout d'abord, il est très important de comprendre que vous devez toujours vous moquer là où la chose que vous essayez de simuler est utilisée comme indiqué dans le unittest.mock Documentation.

Le principe de base est que vous corrigez où un objet est recherché, ce qui n'est pas nécessairement le même endroit que celui où il est défini.

Ensuite, vous devez renvoyer une instance MagicMock en tant que return_value de l'objet patché. Donc, pour résumer cela, vous devez utiliser la séquence suivante.

  • Objet de patch
  • préparer MagicMock à utiliser
  • renvoie le MagicMock que nous venons de créer en tant que return_value

Voici un exemple rapide d'un projet.

connection.py (classe que nous aimerions simuler)

class Connection(object):                                                        
    def execute(self):                                                           
        return "Connection to server made"

file.py (où la classe est utilisée)

from project.connection import Connection                                        


class FileRemoveOp(object):                                                      
    def __init__(self, foo):                                                     
        self.foo = foo                                                           

    def execute(self):                                                           
        conn = Connection()                                                      
        result = conn.execute()                                                  
        return result    

tests/test_file.py

import unittest                                                                  
from unittest.mock import patch, MagicMock                                       
from project.file import FileRemoveOp                                            

class TestFileRemoveOp(unittest.TestCase):                                       
    def setUp(self):                                                             
        self.fileremoveop = FileRemoveOp('foobar')                               

    @patch('project.file.Connection')                                            
    def test_execute(self, connection_mock):
        # Create a new MagickMock instance which will be the
        # `return_value` of our patched object                                     
        connection_instance = MagicMock()                                        
        connection_instance.execute.return_value = "testing"

        # Return the above created `connection_instance`                     
        connection_mock.return_value = connection_instance                       

        result = self.fileremoveop.execute()                                     
        expected = "testing"                                                     
        self.assertEqual(result, expected)                                       

    def test_not_mocked(self):
        # No mocking involved will execute the `Connection.execute` method                                                   
        result = self.fileremoveop.execute()                                     
        expected = "Connection to server made"                                   
        self.assertEqual(result, expected) 
21
flazzarini