unittest模拟函数输出

时间:2017-10-16 21:04:33

标签: mocking python-unittest python-mock

我刚刚在Python2.7中找到了一个模拟库,并希望对我的函数进行单元测试。无论我读什么教程,总是关于课程。我不能让嘲讽功能起作用。 该项目的结构是我在一个函数中使用一些帮助函数来收集和解析数据库中的数据。我想模拟数据库功能和查询功能。对于简单的情况,它看起来像这样:

import unittest
import mock

def queryFnc(arg=0):
    # imitate returned result from a query
    if arg == 0:
        return "queryFunc 0"
    else: return "queryFunc 1"

def parsingFunc():
    # function will parse result returned from a query
    myString = queryFnc().upper()
    return myString

class Test(unittest.TestCase):
    def test_queryFunc0(self):
        self.assertEquals("queryFunc 0", queryFnc(arg=0))
    def test_queryFunc1(self):
        self.assertEquals("queryFunc 1", queryFnc(arg=1))
    @mock.patch('.queryFnc', return_value='queryMock')
    def test_queryMock(self, queryFnc):
        self.assertEquals('queryMock', queryFnc())

    def test_parsingFunc(self):
        self.assertEquals('QUERYFUNC 0', parsingFunc())
    @mock.patch('.queryFnc', return_value='queryMock')
    def test_parsingFuncMock(self):
        self.assertEquals('QUERYMOCK', parsingFunc())

if __name__ == "__main__":
    unittest.main()

我预计@mock.patch将取代通话中的功能,但我可以让它正常工作。我有这个错误:

======================================================================
ERROR: test_queryMock (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "\site-packages\mock\mock.py", line 1297, in patched
    arg = patching.__enter__()
  File "\site-packages\mock\mock.py", line 1353, in __enter__
    self.target = self.getter()
  File "\site-packages\mock\mock.py", line 1523, in <lambda>
    getter = lambda: _importer(target)
  File "\site-packages\mock\mock.py", line 1206, in _importer
    thing = __import__(import_path)
ValueError: Empty module name

有没有办法在另一个函数中使用不同的函数结果? 我被限制使用Python2.7

1 个答案:

答案 0 :(得分:1)

The basic principle is that you patch where an object is looked up。您可以使用mock作业,with比赛管理员和@mock.patch装饰师。我附上了一些包含print语句的代码,显示函数查找原始函数和模拟对象的位置。

# CASE 1 taking query as mock inside test_ function
def test_queryMock1(self):
    queryFnc = mock.Mock(return_value = 'case1')
    print("Case 1 inside test_ after mock assignemnt", queryFnc(), queryFnc(1))
    self.assertEquals('case1', queryFnc(1))
print("Case1 after outside", queryFnc(), queryFnc(1))

# CASE 2 contest management with
def test_queryMock2(self):
    print("Case 2 inside test", queryFnc(), queryFnc(1))
    with mock.patch('__main__.queryFnc', return_value='case2'):
        print("Case 2 after with", queryFnc(), queryFnc(1))
        self.assertEquals('case2', queryFnc())
print("Case 2 outside", queryFnc(), queryFnc(1))  

# CASE 3 patching
@mock.patch('__main__.queryFnc', return_value='case3')
def test_queryMock3(self, *args):
    self.assertEquals('case3',queryFnc())

# CASE 4 using contest management for nested function
def test_InsideWith(self):
    print("Case 4 inside test_", queryFnc(), queryFnc(1)) 
    #with mock.patch('__main__.queryFnc', side_effect=mockText) as mock_function_obj:
    with mock.patch('__main__.queryFnc', return_value='case4'):
        print("Case 4 inside with", queryFnc(), queryFnc(1))
        self.assertEquals('CASE4', parsingFunc())
print("Case 4 outside", queryFnc(), queryFnc(1))

# CASE 5 using patch decorator
@mock.patch('__main__.queryFnc', return_value='case5')
def test_Patch(self, *args):
    print("Case 5 inside test_ after patch", queryFnc(), queryFnc(1))
    self.assertEquals('CASE5', parsingFunc())
    print("Case 5 inside test_, assert", queryFnc(), queryFnc(1))
print("Case 5 outside", queryFnc(), queryFnc(1))

请注意,在补丁中,模块被指定为要修补的__main__。如果您尝试使用模块名称,则可以看到它如何更改修补程序行为。