模拟整个python类



我试图用python做一个简单的测试,但是我不能弄清楚如何完成模拟过程。

这是类和def code:

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.")
下面是我对execute函数的测试:

@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)

由于execute方法试图建立连接,我需要模拟它,我不想建立真正的连接,只是返回一些模拟。我怎么才能做到呢?我习惯用Java做测试,但从来没有用过python.

首先,理解您总是需要Mock,如果您试图模拟的东西是在unittest.mock文档中说明的那样使用的,这一点非常重要。

基本原则是,你在一个对象被查找的地方进行修补,这与它的定义位置不一定相同

接下来你需要做的是返回一个MagicMock实例作为补丁对象的return_value。因此,为了总结这一点,您需要使用以下序列。

    <
  • 补丁对象/gh>
  • 准备MagicMock使用
  • 返回我们刚刚创建的MagicMock作为return_value

这里是一个项目的快速示例。

connection.py(我们想要模拟的类)

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

file.py(使用Class的地方)

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    

测试/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) 

我发现这个简单的解决方案在python3中有效:您可以在第一次导入类之前替换整个类。假设我必须从real.manager中模拟类'Manager'

class MockManager:
    ...
import real.manager
real.manager.Manager = MockManager

如果没有更好的地方,可以在init.py中进行此替换。它也可以在python2中工作,但我没有检查。

相关内容

  • 没有找到相关文章

最新更新