如何Mock验证码生成函数测试Redis缓存?是否需测试完整视图?
验证码缓存测试相关问题解答
问题描述
- 如何Mock验证码生成函数,让其返回指定验证码,以此测试验证码保存至Redis缓存的功能?
- 是否需要测试整个视图函数?
我提供的相关代码
视图代码
def post(self, request): serializer = ReviewerSignUpSerializer(data=request.data) serializer.is_valid(raise_exception=True) phone = serializer.validated_data.get("phone") confirmation_code = get_confirmation_code() cache.set( key=str(phone), value=confirmation_code, timeout=settings.CONFIRMATION_CODE_LIFETIME ) send_sms_task.apply_async([confirmation_code, str(phone)])
验证码生成函数
def get_confirmation_code() -> str: seq = list(map(lambda x: str(x), range(10))) shuffle(seq) code = choices(seq, k=settings.INVITE_CODE_LENGTH) return "".join(code)
测试代码
def test_saving_confirmation_code_in_cache(self, client, cache): phone = "+79389999999" generated_code = "9999" with patch("api.v1.authentication.utils.get_confirmation_code", return_value=generated_code): client.post(reverse('api:v1:signup'), data={'phone': phone}) confirmation_code = cache.get(str(phone)) assert confirmation_code is not None assert confirmation_code == generated_code
解答
一、Mock验证码生成函数的正确方式
你当前的测试逻辑没问题,但要注意**patch的路径必须是视图文件中实际导入get_confirmation_code的路径**,而非函数定义的路径。
举个例子:如果你的视图文件是api/v1/authentication/views.py,且导入语句是from .utils import get_confirmation_code,那测试时必须patchapi.v1.authentication.views.get_confirmation_code,而不是api.v1.authentication.utils.get_confirmation_code——这是很多开发者容易踩的坑。
你的测试流程是正确的:
- 用
patch上下文管理器替换目标函数,指定返回值为预设的验证码 - 发送POST请求触发视图逻辑
- 从缓存中取值,断言与预设验证码一致
二、是否需要测试整个视图函数?
分场景来看:
- 单元测试:只需聚焦验证码存入缓存这一核心逻辑即可,也就是你现在写的测试。至于短信发送任务
send_sms_task,可以单独Mock它,验证是否被正确调用且参数无误,无需真的触发短信发送。 - 集成测试:可以覆盖视图的完整流程,包括序列化验证、缓存存储、任务调用,但同样要Mock短信服务、验证码生成这类外部依赖,避免因依赖外部服务导致测试不稳定。
简单来说:单元测试聚焦单一功能点,集成测试覆盖完整流程,但都要合理Mock外部依赖。
内容的提问来源于stack exchange,提问作者aleksandrkomyagin
相关产品推荐
相关产品推荐

