override_settings
djangoでテストをする際にoverride_settingsを使うとsettings.pyの内容を一時的に変更することができます。
しかしコード内でクラス変数としてsettings.pyの値を使っていると効かない場合があります。
ユーザー登録をする際にメールで有効期限付きのアクティベーションリンクを送るようなシステムを例に、うまく行かなかった例を説明します。
testコード
テストコードは以下のようにして、ACTIVATION_TIMEOUT_SECONDS
という値がsettings.pyで運用時に使う値が設定されています。テストでは、1秒にして期限切れのリンクを踏んでちゃんとアクティベートされないか確認しています。
tests.py
class MailActivationTests(TestCase):
@override_settings(ACTIVATION_TIMEOUT_SECONDS=1)
def test_create_expired_user(self):
User = get_user_model()
url = reverse('users:user_create')
post_data = {
'email':'expired@mail.com',
'password1':'abcd1234',
'password2':'abcd1234'}
self.client.post(url, post_data)
user = User.objects.get(email='expired@mail.com')
self.assertFalse(user.is_active)
url = get_activation_url()
sleep(2)
res = self.client.get(url, follow=True)
user = User.objects.get(email='expired@mail.com')
self.assertFalse(user.is_active)
うまく行かなかった例
views.py
from django.conf import settings
from django.core.signing import loads
class UserCreateComplete(generic.TemplateView):
template_name = 'users/user_create_complete.html'
timeout_sec = settings.ACTIVATION_TIMEOUT_SECONDS
def get(self, request, **kwargs):
token = kwargs.get('token')
try:
user_pk = loads(token, max_age=self.timeout_sec)
...
うまく行った例
views.py
from django.conf import settings
from django.core.signing import loads
class UserCreateComplete(generic.TemplateView):
template_name = 'users/user_create_complete.html'
def get(self, request, **kwargs):
timeout_sec = settings.ACTIVATION_TIMEOUT_SECONDS
token = kwargs.get('token')
try:
user_pk = loads(token, max_age=timeout_sec)
...
クラス変数にするとoverrideされない
上記の例のようにクラス変数でsettings.pyの値を使っているとoverrideされないようです。メソッド内で値を取得するようにすると、上記のテストコードがパスされました!