无法在Django unittest中测试密码更改

时间:2016-05-04 02:52:16

标签: django python-unittest django-unittest

我正在尝试为Django应用程序编写集成测试,以测试密码是否已从其他API更改。但是,在调用密码更改API后,测试新密码不起作用。

我在这里做的是:我通过休息呼叫将密码更改为johnjohn,然后尝试检查密码是否实际更改

我的单元测试文件

import json
import urllib
import urllib2

import requests
from django.contrib.auth.models import User

from django.test import TestCase
from adaptors.redis_class import DjangoRedis


class PasswordChange(TestCase):
    def setUp(self):
        User.objects.create_user(username='john', email='john@john.com', password='john')
        # class for redis access  
        r = DjangoRedis()
        r.set("email:john@john.com", '0' * 40, ex=3600)
        r.set('0' * 40, "email:john@john.com", ex=3600)
    def test_change_password(self):
        # Fake url I set through redis
        url = 'http://127.0.0.1:8000/reset/' + '0' * 40 + '/'
        r = requests.get(url)
        csrf_token = r.content.split('csrf_token')[1].split('"')[2]
        payload = {'csrfmiddlewaretoken': csrf_token, 'payload': json.dumps({'password': 'johnjohn'})}
        headers = {'Cookie': 'csrftoken=' + csrf_token}
        data = urllib.urlencode(payload)
        req = urllib2.Request(url, data, headers)
        response = urllib2.urlopen(req)
        json_res = json.loads(response.read())

        # This doesn't fail
        self.assertEqual(json_res['password_changed'], True)
        u = User.objects.get(username='john')

        # This fails
        self.assertEqual(u.check_password('johnjohn'),True)

我的观点

import hashlib
import random

from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404
from django.http import JsonResponse
from django.shortcuts import render
from django.views.generic import View

from adaptors.redis_class import DjangoRedis
from constants import PASSWORD_RESET
from tasks import send_email
from util.rest import get_payload
class ResetPage(View):
    def post(self, requests, reset_token):
        r = DjangoRedis()
        token = r.get(reset_token)
        if token is None:
            return JsonResponse({"token": False})
        payload = get_payload(requests.POST)
        try:
            email = token.split(':')[1].lower()
            u = User.objects.get(email=email)
            u.set_password(payload['password'])
            u.save()
            r.delete(reset_token)
            r.delete('email:' + email)
            return JsonResponse({'password_changed': True})
        except ValueError:
            return JsonResponse({"password_changed": False, 'error': "can't get your email from the database (E01)"})
        except ObjectDoesNotExist:
            return JsonResponse({"password_changed": False, 'error': "User doesn't exist (E02)"})

    def get(self, requests, reset_token):
        r = DjangoRedis()
        if not r.get(reset_token):
            raise Http404
        return render(requests, "login/reset.html", {'token': reset_token})

unittest文件在rest_pass_login_tests.py目录中称为unittests

我使用以下命令运行它。

./manage.py test unittests/ --pattern="rest_pass_login_tests.py"

当我通过浏览器正常测试时,密码更改工作正常。但是,当我尝试通过unittest检查密码是否已更改时,我收到的密码无效。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

我使用dev服务器来运行unittests。当我更改密码时,我实际上是发布到开发服务器而不是测试服务器。

这是我的新单元测试

import json

from django.contrib.auth.models import User
from django.test import Client
from django.test import TestCase

from adaptors.redis_class import DjangoRedis


class PasswordChange(TestCase):
    def setUp(self):
        User.objects.create_user(username='john', email='john@john.com', password='john')
        r = DjangoRedis()
        r.set("email:john@john.com", '0' * 40, ex=3600)
        r.set('0' * 40, "email:john@john.com", ex=3600)

    def test_change_password(self):
        c = Client()
        payload = {'payload': json.dumps({'password': 'johnjohn'})}

        url = '/reset/' + '0' * 40 + '/'
        res = c.post(url, payload)
        res = res.json()
        self.assertEqual(res['password_changed'], True)
        u = User.objects.get(username='john')
        self.assertEqual(u.check_password('johnjohn'), True)

如果您要使用selenium IDE,请确保StaticLiveServerTestCase而不是unittest固有。关注this example。另外,不要忘记将此变量self.base_url更改为self.live_server_url

这是我的setUp方法

self.base_url = self.live_server_url

感谢fipskoterpillar帮助我进入IRC频道,感谢aks在我的评论下。

答案 1 :(得分:0)

您没有像您的观点所期望的那样制作http post

以下是使用urllib2制作帖子的方法:Making a POST call instead of GET using urllib2

但是,既然你已经使用requests模块,为什么不这样做呢:

url = 'http://127.0.0.1:8000/reset/' + '0' * 40 + '/'
payload = {'csrfmiddlewaretoken': csrf_token, 'payload': json.dumps({'password': 'johnjohn'})}
headers = {'Cookie': 'csrftoken=' + csrf_token}
r = requests.post(url, data=payload, headers=headers)
json_res = json.loads(r.content)

也许可以尝试调试/打印json_res的值来检查是否还有其他意外情况。

另请注意,这是一个集成测试,因为您正在通过http进行测试,因此您的urls.py,views.py甚至settings.py正在作为其中的一部分进行测试。