Django单元测试:Mock外部API的正确方式是什么?
搞定Mock外部API的单元测试方案
嘿,我来帮你解决这个Mock外部API的问题!核心思路就是把utils.get_original_title_and_name这个调用外部API的函数给“替换”掉,让它在单元测试时不发起真实请求,而是返回我们预设的模拟数据,这样就能专注测试Book.save()的逻辑,完全不用依赖外部服务。
下面是具体的实现步骤和代码示例,我假设你用的是Django测试框架(毕竟是Django模型):
1. 先导入测试需要的工具
在你的测试文件(比如tests/test_models.py)里,先把需要的模块导进来:
from django.test import TestCase from unittest.mock import patch from .models import Book from . import utils
2. 编写测试用例:Mock掉外部API调用
我们可以用@patch装饰器或者上下文管理器with patch(...)来临时替换目标函数,两种方式都好用,看你偏好哪种。
场景1:测试有ISBN且API返回数据的情况
class BookModelTest(TestCase): def test_save_with_isbn_and_valid_api_response(self): # 用上下文管理器Mock掉utils里的那个API调用函数 with patch('你的app名.utils.get_original_title_and_name') as mock_api_call: # 给Mock函数设置预设的返回值,模拟API返回的有效数据 mock_api_call.return_value = { 'author': 'J.K. Rowling', 'title': 'Harry Potter and the Philosopher\'s Stone' } # 创建一个带ISBN的Book实例 book = Book( title='哈利波特与魔法石(中文版)', isbn='9780747532743' ) # 调用save方法 book.save() # 验证Mock函数确实被调用了,而且传入的ISBN是对的 mock_api_call.assert_called_once_with('9780747532743') # 验证save之后,original_author被正确赋值了 self.assertEqual(book.original_author, 'J.K. Rowling')
场景2:测试有ISBN但API没返回数据的情况
def test_save_with_isbn_but_empty_api_response(self): with patch('你的app名.utils.get_original_title_and_name') as mock_api_call: # 让Mock函数返回None,模拟API没查到数据的情况 mock_api_call.return_value = None book = Book( title='自定义书名', isbn='1234567890123' ) book.save() # 验证API确实被调用了,但original_author还是空的 mock_api_call.assert_called_once_with('1234567890123') self.assertIsNone(book.original_author)
场景3:测试没有ISBN的情况(完全不调用API)
def test_save_without_isbn(self): with patch('你的app名.utils.get_original_title_and_name') as mock_api_call: book = Book( title='一本没有ISBN的书' ) book.save() # 验证API函数根本没被调用过 mock_api_call.assert_not_called()
几个关键注意点
- Mock的路径一定要对:你得patch函数被实际调用的那个路径!比如在
Book.save()里,是从.utils导入的get_original_title_and_name,所以要patch你的app名.utils.get_original_title_and_name,千万别写错路径,不然Mock会失效。 - 灵活控制Mock的返回值:除了
return_value,你还可以用side_effect来模拟异常(比如API请求失败的情况),覆盖更多业务场景。 - 验证调用情况:用
assert_called_once_with()、assert_not_called()这些方法,确保你的Mock函数被正确调用,参数也符合预期,这样能保证测试的严谨性。
这样一来,你就能完全隔离外部API的影响,专心测试save()方法的逻辑正确性啦!
内容的提问来源于stack exchange,提问作者kotmsk
相关产品推荐
相关产品推荐

