Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python如何重用Mock以避免多次编写Mock.patch?_Python_Python 3.x_Flask_Mocking_Python Mock - Fatal编程技术网

Python如何重用Mock以避免多次编写Mock.patch?

Python如何重用Mock以避免多次编写Mock.patch?,python,python-3.x,flask,mocking,python-mock,Python,Python 3.x,Flask,Mocking,Python Mock,给定如下代码: import flask import time app = flask.Flask(__name__) def authorize(): print('starting authorize io') time.sleep(1) print('done authorize io') class BlockingIo(): def __init__(self, n): self.n = n def do(self):

给定如下代码:

import flask
import time

app = flask.Flask(__name__)

def authorize():
    print('starting authorize io')
    time.sleep(1)
    print('done authorize io')

class BlockingIo():
    def __init__(self, n):
        self.n = n
    def do(self):
        print('starting blocking io')
        time.sleep(1)
        print('ending blocking io')

@app.route('/', methods=['GET'])
@app.route('/<int:n>/', methods=['GET'])
def foo(n=1):
    authorize()
    b = BlockingIo(n)
    b.do()
    return str(n), 200

#app.run(port=5000)
m = mock.something('__main__.authorize')
m2 = mock.something('__main__.BlockingIo.do')    

class TestBlockingIo(unittest.TestCase):
    def test_1(self):
        r = testapp.get('/1/')
        self.assertEquals(r.data, b'1')
    def test_2(self):
        r = testapp.get('/2/')
        self.assertEquals(r.data, b'2')
但是,我不想一遍又一遍地写出
@mock.patch
decorator

我知道我们可以使用类装饰器,我可以使用子类来实现更高的可重用性:

@mock.patch('__main__.authorize')
@mock.patch('__main__.BlockingIo.do')
class TestBlockingIo(unittest.TestCase):
    def test_1(self, m, m2):
        r = testapp.get('/1/')
        self.assertEquals(r.data, b'1')
    def test_2(self, m, m2):
        r = testapp.get('/2/')
        self.assertEquals(r.data, b'2')
但是,这会强制类中的所有测试函数为每个模拟获取一个额外参数。如果此类中的测试不需要模拟
阻塞IO
授权
,该怎么办

我想我想要的是一种实现以下目标的方法:

import flask
import time

app = flask.Flask(__name__)

def authorize():
    print('starting authorize io')
    time.sleep(1)
    print('done authorize io')

class BlockingIo():
    def __init__(self, n):
        self.n = n
    def do(self):
        print('starting blocking io')
        time.sleep(1)
        print('ending blocking io')

@app.route('/', methods=['GET'])
@app.route('/<int:n>/', methods=['GET'])
def foo(n=1):
    authorize()
    b = BlockingIo(n)
    b.do()
    return str(n), 200

#app.run(port=5000)
m = mock.something('__main__.authorize')
m2 = mock.something('__main__.BlockingIo.do')    

class TestBlockingIo(unittest.TestCase):
    def test_1(self):
        r = testapp.get('/1/')
        self.assertEquals(r.data, b'1')
    def test_2(self):
        r = testapp.get('/2/')
        self.assertEquals(r.data, b'2')
如何重用我的
@mock.patch(“\uu main\uuuuu.authorize”)
@mock.patch(“\uu main\uuuuuu.BlockingIo.do”)
以避免重复测试?

您可以在
设置中使用并重用它们

补丁很好,因为当您完成测试时,您可以“取消补丁”,这意味着您不会像某些其他测试可能需要在实际代码上运行一样,永远让事情处于模拟状态

在上面的链接上,您将看到以下代码:

>>> class MyTest(TestCase):
...     def setUp(self):
...         patcher = patch('package.module.Class')
...         self.MockClass = patcher.start()
...         self.addCleanup(patcher.stop)
...
...     def test_something(self):
...         assert package.module.Class is self.MockClass
...
它工作得很好,但我并不喜欢为每个补丁调用
patch()
start()
addCleanup()

您可以很容易地将其考虑到基类中,以便在测试类中重用:

class PatchMixin:

    def patch(self, target, **kwargs):
        p = mock.patch(target, **kwargs)
        p.start()
        self.addCleanup(p.stop)

class TestBlockingIo(unittest.TestCase, PatchMixin):

    def setUp(self):
        self.patch('__main__.authorize')
        self.patch('__main__.BlockingIo.do')

    def test_1(self):
        r = testapp.get('/1/')
        self.assertEquals(r.data, b'1')

    def test_2(self):
        r = testapp.get('/2/')
        self.assertEquals(r.data, b'2')

如果您想在测试中配置模拟,请从
补丁
存储并返回
ps.start()