无法使用mock_open()在模拟函数中测试全局值

时间:2019-06-13 14:18:04

标签: python python-2.7 pytest python-mock

我正在尝试使用mock_open()来测试我的应用程序Mocking file reads using patch decorator and side_effect,但是无法检查来自 test 函数的全局值集。仅当函数返回值时才起作用。

我的应用程序代码片段类似于

#!/usr/bin/env python
 # -*- coding: utf-8 -*-

thresh_dict = {}
allowed_san_dict = {}
max_eval_count = ""
clear_eval_count = ""

def generate_cfg_thresh_map():
    """ For generating a mapping table containing the thresholds for each of the
    production devices. The file is read one line at a time and split on whitespace
    to get the individual fields
    """

    global allowed_san_dict
    global max_eval_count
    global clear_eval_count
    try:
        with open ('/opt/config/pwr_thresh_cfg', 'r') as fh:
            for line in fh:
                split_line = line.split()
                if line.startswith("ENTRY_THRESH_COUNT"):
                    max_eval_count = int(split_line[1])
                elif line.startswith("EXIT_THRESH_COUNT"):
                    clear_eval_count = int(split_line[1])
                else:
                    thresh_dict[split_line[0]]  = [int(split_line[1]), int(split_line[2]), int(split_line[3])]
                    allowed_san_dict[split_line[0]] = int(split_line[4])

    except Exception as error:
        log_to_journal('read failed from pwr_thresh_cfg')

test_app.py文件看起来像

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Include require py.test libraries for the suite to run
import unittest
import pytest
import mock

import app

from mock import patch, mock_open

class ReportMonitor(unittest.TestCase):
    def test_generate_cfg_thresh_map(self):
        with patch('app.open', mock_open(read_data='ENTRY_THRESH_COUNT 200')) as _:
            app.generate_cfg_thresh_map()
            assert app.max_eval_count == 200
            print('value for %s' % (app.max_eval_count))
            print('value for %s' % (app.generate_cfg_thresh_map()))

问题是我想对max_eval_count函数中设置的generate_cfg_thresh_map()的值进行断言。由于该值是在全局变量中设置的,而不是从函数返回的,因此我无法在测试用例中声明该值。我不能从函数中使用return,即完全不更改应用程序代码。

我该怎么做?即运行被测函数,并检查函数为测试字符串设置的值,并根据函数设置的值声明单元测试用例。

1 个答案:

答案 0 :(得分:1)

引用mock_open docs

  

read_data 是用于返回文件句柄的read()readline()readlines()方法的字符串。调用这些方法将从 read_data 中获取数据,直到数据耗尽。

这意味着在迭代模拟文件对象时将不会调用read_data。一个简单的解决方法是将generate_cfg_thresh_map函数的实现更改为:

def generate_cfg_thresh_map():
    ...
    try:
        with open ('/opt/config/pwr_thresh_cfg', 'r') as fh:
            for line in fh.readlines():
                ...

如果您无法更改函数,则可以增强mock_open返回的模拟对象:

Python 3

class ReportMonitor(unittest.TestCase):
    def test_generate_cfg_thresh_map(self):
        m = mock_open(read_data='ENTRY_THRESH_COUNT 200')
        m.return_value.__iter__ = lambda self: self
        m.return_value.__next__ = lambda self: next(iter(self.readline, ''))
        with patch('app.open', m):
            app.generate_cfg_thresh_map()
            assert app.max_eval_count == 200

Python 2

class ReportMonitor(unittest.TestCase):
    def test_generate_cfg_thresh_map(self):
        m = mock_open(read_data='ENTRY_THRESH_COUNT 200')
        m.return_value.__iter__ = lambda self: iter(self.readline, '')
        with patch('app.open', m):
            app.generate_cfg_thresh_map()
            assert app.max_eval_count == 200

积分:Customizing unittest.mock.mock_open for iteration