首页 > 解决方案 > 如何在 Python 单元测试中修补用于内部方法的类?

问题描述

假设我有一个 Flask 应用程序,它有一个从数据库获取资源的路径,有三个文件:

  1. 带有端点 (api.py) 的 Flask“主”应用程序
  2. 一个数据库类,用于处理连接(database.py)
  3. 特定资源的域类 (resource.py)

api 文件如下所示:

from src.objects.resource import Resource

@api.route('/api/resource/<id>', methods=['GET'])
def get_resource(id):
    records = Resource().query(id)
    return records

Resource对象在其构造函数中具有正在构造的数据库类的实例:

class Resource(Database):
    def __init__(self):
        Database.__init__(self, 'resource')

该类Database连接到数据库__init__

class Database:
    def __init__(self, entity):
        self.conn = psycopg2.connect(os.getenv('DB_URI', 'localhost'))

我现在真正想要的是创建一个单元测试来模拟当 API 方法get_resource被命中时会发生什么(不是 HTTP 调用会发生什么,而是将有效和无效的 id 作为参数提供会发生什么)。

由于 Resource 对象现在主要用作数据库检索的接口,我想在我的测试中模拟它,所以当方法构造它的实例时,Resource它会在测试期间得到模拟,而不是实际的 Resource 实例。

但是,我看到的是真正的构造函数被调用。测试代码如下:

import unittest
from unittest.mock import patch
import json
import src.api
from flask import Flask


class TestApi(unittest.TestCase):

    @patch('src.objects.resource.Resource')
    def test_get_resource(self, mock_obj):

        # given
        instance = mock_obj.return_value
        instance.query.return_value = {
            'id': 1,
            'name': 'Resource\'s Name'
        }

        # when
        with Flask(__name__).app_context():
            # then
            result = json.loads(src.api.get_resource(1).get_data())

            self.assertEqual(True, 'data' in result)
            self.assertEqual(True, 'error' in result)
            self.assertEqual(False, result['error'])

ProgrammingErrorpsycopg2模块中得到一个(我不想被调用):

E psycopg2.ProgrammingError: invalid dsn: missing "=" after "localhost" in connection info string

我应该模拟__init__Resource 对象的方法吗?如果是这样,怎么做?

标签: pythonunit-testingmonkeypatching

解决方案


推荐阅读