加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

模拟一个在方法调用后更改实例变量的python类?

发布时间:2020-12-20 13:44:50 所属栏目:Python 来源:网络整理
导读:我有一些代码,其中对方法update()的调用会更改某些实例变量的值.我使用更改的值来保留循环.这是我的代码的简化示例: def do_stuff(self): # get a new instance of A a = get_a() while True: a.update() if a.state == 'state': break 这个类的简单版本(我
我有一些代码,其中对方法update()的调用会更改某些实例变量的值.我使用更改的值来保留循环.这是我的代码的简化示例:

def do_stuff(self):
    # get a new instance of A
    a = get_a()
    while True:
        a.update()
        if a.state == 'state':
            break

这个类的简单版本(我无法更改类,因为它是第三方库):

class A(object):
    def __init__(self):
        self.state = ''

    def update(self):
        # call to external system
        self.state = extern_func()

现在我想通过模拟类A来测试我的函数do_stuff().为了测试函数的每个方面,我想拥有所有不同的状态值,并且它应该在每次调用a.update()之后改变(迭代不同的状态).

我开始使用这个设置进行单元测试:

from mock import Mock,patch
import unittest

class TestClass(unittest.TestClass):

    @patch('get_a')
    def test_do_stuff(self,mock_get_a):
         mock_a = Mock(spec=A)
         mock_get_a.return_value = mock_a

         # do some assertions

我能用Mock实现这种行为吗?
我知道Mock有side_effect为连续的函数调用返回不同的值.但是我无法找到一种方法来在函数调用后更改实例变量的值?

解决方法

建立:

from mock import Mock,MagicMock,patch

sep = '***********************n'

# non-mock mocks
def get_a():
    return A()
def extern_func():
    return 'foo'

def do_stuff(self):
    # get a new instance of A
    a = get_a()
    while True:
        a.update()
        print a.state
        if a.state == 'state':
            break

class A(object):
    def __init__(self):
        self.state = ''

    def update(self):
        # call to external system
        self.state = extern_func()

正如@Simeon Viser所提到的,模拟extern_func会起作用:

print sep,'patch extern'
mock = MagicMock(side_effect = [1,2,3,4,'state'])
@patch('__main__.extern_func',mock)
def foo():
    do_stuff(3)
foo()

>>> 
***********************
patch extern
1
2
3
4
state

side_effect可以是一个函数,您可以使用auto_spec = True参数模拟未绑定的方法A.update.

使用上下文管理器:

print sep,'patch update context manager call do_stuff'
def update_mock(self):
    self.state = mock()
mock = MagicMock(side_effect = [1,'state'])
with patch.object(A,'update',autospec = True) as mock_update:
    mock_update.side_effect = update_mock
    do_stuff(3)

>>>
***********************
patch update context manager call do_stuff
1
2
3
4
state

使用装饰者:

print sep,'patch update decorator test_do_stuff'
def update_mock(self):
    self.state = mock()
mock = MagicMock(side_effect = [1,'state'])
@patch.object(A,autospec = True,side_effect = update_mock)
def test_do_stuff(self):
    do_stuff(3)
test_do_stuff()

>>>
***********************
patch update decorator test_do_stuff
1
2
3
4
state

警告:我从来没有编写过全面的单元测试,而且最近才开始阅读模拟文档,所以尽管我似乎完成了这项工作,但我无法评论它在你的测试方案中的功效.编辑欢迎.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读