【发布时间】:2019-07-31 23:20:48
【问题描述】:
给定代码如下:
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)
我希望能够为GET /n/ 编写几个测试,每个测试都模拟authorize 和BlockingIO(n):
app.testing = True
testapp = app.test_client()
import unittest
from unittest import mock
mock.patch('__main__.authorize')
class TestBlockingIo(unittest.TestCase):
@mock.patch('__main__.authorize')
@mock.patch('__main__.BlockingIo.do')
def test_1(self, m, m2):
r = testapp.get('/1/')
self.assertEquals(r.data, b'1')
@mock.patch('__main__.authorize')
@mock.patch('__main__.BlockingIo.do')
def test_2(self, m, m2):
r = testapp.get('/2/')
self.assertEquals(r.data, b'2')
unittest.main()
但是,我不想一遍又一遍地写出@mock.patch装饰器。
我知道我们可以使用类装饰器,并且我可以子类化以获得更多的可重用性:
@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')
但是,这会强制类中的所有测试函数为每个模拟采用一个额外的参数。如果我在这个类中有不需要模拟 BlockingIo 或 authorize 的测试怎么办?
我想我想要的是一种方法来执行以下操作:
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('__main__.authorize') 和 @mock.patch('__main__.BlockingIo.do') 以避免重复自己通过测试?
【问题讨论】:
标签: python python-3.x flask mocking python-mock