我在这里有一个简单的应用示例:
说我有这段代码,可以处理用户请求以获取存储在数据库中的书籍清单。
from .handlers import all_books
@apps.route('/show/all', methods=['GET'])
@jwt_required
def show_books():
user_name = get_jwt_identity()['user_name']
all_books(user_name=user_name)
在handlers.py
中,我有:
def all_books(user_name):
db = get_db('books')
books = []
for book in db.books.find():
books.append(book)
return books
但是在编写单元测试时,我意识到如果我在get_db()
中使用all_books()
,则很难对方法进行单元测试。
所以我认为这是个好方法。
from .handlers import all_books
@apps.route('/show/all', methods=['GET'])
@jwt_required
def show_books():
user_name = get_jwt_identity()['user_name']
db = get_db('books')
collection = db.books
all_books(collection=collection)
def all_books(collection):
books = []
for book in collection.find():
books.append(book)
return books
我想知道什么是好的设计? 让所有代码都在一个地方做一件事情,如第一个示例或第二个示例一样。
对我来说,第一个似乎更清晰,因为它把所有相关的逻辑都放在一个地方。但是在第二种情况下更容易通过伪造的集合进行单元测试。
答案 0 :(得分:1)
您可能应该使用模拟库,请参见:https://docs.python.org/3/library/unittest.mock.html#quick-guide
(如果您使用python2,则需要pip install mock
)
def test_it():
from unittest.mock import Mock,patch
with patch.object(get_db,'function',Mock(return_value=Mock(books=[1,2,3]))) as mocked_db:
x = get_db("ASDASD")
console.log(x.books)
# you can also do cool stuff like this
assert mocked_db.calledwith("ASDASD")
对于您来说很粗糙,您将必须构造稍微复杂一点的对象
my_mocked_get_db = Mock(return_value=Mock(books=Mock(find=[1,2,3,4])))
with patch.object(get_db,'function',my_mocked_get_db) as mocked_db:
x = get_db("ASDASD")
print(x.books.find())