Django测试中mock未被调用:如何正确模拟validate_sns_token函数?
validate_sns_token in Your Django Test It looks like your mock isn't replacing the original function because of how Python's mocking system targets references. Let's break down the problem and fix it step by step.
Why Your Current Mock Isn't Working
Even though you're targeting user.serializers.validate_sns_token, there are a few edge cases where this might not replace the function that's actually being called in your serializer's create method:
- String-based paths can be error-prone if your project structure has nested modules, or if imports are cached in a way that bypasses the patch.
- If your
createmethod references the function directly (as a local name in theserializers.pyfile), you need to ensure the patch targets the exact reference being used.
Solution 1: Use patch.object for Reliable Mocking
Instead of using a string path, use patch.object to directly target the function on the imported serializers module. This avoids path-related mistakes and ensures you're overriding the exact reference your create method uses.
Here's the updated test code:
from django.test import TestCase from unittest.mock import patch from user import serializers # Import the module directly from rest_framework import status class UserCreationTest(TestCase): # ... your setup and other test methods ... @patch.object(serializers, 'validate_sns_token', return_value=True) def test_can_create_user(self, validate_mock): """Test that user can be created without logging in""" user_payload = self.generate_user_payload() resp = self.client.post( CREATE_USER_URL, user_payload, ) # Verify the mock was called self.assertTrue(validate_mock.called) # Verify the response is successful self.assertEqual( resp.status_code, status.HTTP_200_OK, )
Solution 2: Verify Your Patch Path (If You Prefer String-Based Patching)
If you want to stick with the string path approach, confirm the exact module path of the function being called:
- Add this line to your test file to check the function's module:
from user.serializers import validate_sns_token print(validate_sns_token.__module__) # Should output "user.serializers" - If the output is different (e.g.,
user.api.serializers), update your patch path to match that exact string.
Additional Checks to Rule Out Other Issues
- Ensure your payload has required fields: Double-check that
generate_user_payload()includessns_id,sns_type, andtoken—if these are missing, yourcreatemethod might skip callingvalidate_sns_tokenentirely. - Debug mock calls: Add
print(validate_mock.mock_calls)to your test to see exactly when (or if) the mock is being invoked, and what arguments are passed to it. This will help confirm if the mock is being hit at all.
By using patch.object, you're directly modifying the function reference in the serializers module that your create method uses—this guarantees the original function won't run, and your mock's return value will be used instead.
内容的提问来源于stack exchange,提问作者forJ

