D
D
Danil Valiulin2016-06-13 18:05:18
Test Driven Development
Danil Valiulin, 2016-06-13 18:05:18

Flask. Why is the test not passing data to the view?

Hello.

I'm trying to learn TDD. Wrote a little test

import unittest

from app import app, db, bcrypt
from app.models import User
from flask_testing import TestCase


class BaseTestCase(TestCase):

    def create_app(self):
        app.config['TESTING'] = True
        app.config['CSRF_ENABLED'] = False
        app.config['WTF_CSRF_ENABLED'] = False
        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
        return app

    def setUp(self):
        db.create_all()
        user = User(
                username="admin",
                email="[email protected]",
                password=bcrypt.generate_password_hash("admin")
            )
        db.session.add(user)
        db.session.commit()

    def tearDown(self):
        db.session.remove()
        db.drop_all()


class TestLoginMixin(BaseTestCase):

    def login_user(self, login, password):

        with self.app.test_request_context('/account/login/'):
            self.app.preprocess_request()
            data = {'username': login, 'password': password}
            response = self.client.post('/account/login/', data=data)

            return response


class LoginTest(TestLoginMixin):

    user = {'username': 'admin', 'password': 'admin'}

    def test_change_password(self):
        """TEST: change password"""

        self.login_user(**self.user)
        response = self.client.post('/account/change_password/', data=dict(
            old=self.user['password'],
            new='new',
            confirm='new'
        ))
        print(response.data, response.status_code)

if __name__ == '__main__':
    unittest.main()


Authorization works fine, but when I send data to change the password, an error
if not bcrypt.check_password_hash(current_user.password, data['old']):
TypeError: 'NoneType' object is not subscriptable

because nothing came to the view. I do not understand why the test does not send data.

view code
class AccountView(FlaskView):

    @route('/login/', methods=['POST'])
    @check_login
    def login(self):
        form = LoginForm(data=request.get_json())
        if form.validate():
            try:
                user = User.query.filter_by(username=form.username.data).first()
            except SQLAlchemyError as e:
                # TODO: loging exeption e
                return return_response(500, jsonify(error='Произошлка ошибка во время запроса.'))
            if user is None:
                return return_response(404, jsonify(error='Пользователь не найден'))
            if bcrypt.check_password_hash(user.password, form.password.data):
                login_user(user)
                return '', 200
            return return_response(404, jsonify(error='Не правильно введен логин или пароль'))

    @login_required
    def logout(self):
        logout_user()
        return '', 200

    @login_required
    @route('/change_password/', methods=['POST'])
    def change_password(self):
        data = request.get_json()
        if not bcrypt.check_password_hash(current_user.password, data['old']):
            return return_response(404, jsonify(error='Старый пароль введен не верно'))
        if not data['new'] == data['confirm']:
            return return_response(404, jsonify(error='Новый пароль и подтверждение пароля не совпадают'))
        try:
            User.query.filter_by(id=current_user.id).update({
                'password': bcrypt.generate_password_hash(data['new'])
            })
            db.session.commit()
        except SQLAlchemyError as e:
            return return_response(500, jsonify(error='Произошла ошибка во время запроса.'))
        return '', 200

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Ankou, 2017-05-27
@Ankou

Hi.
you need a json object in request.get_json() , this can be achieved either by request.get_json(force=True), i.e. force any incoming message to be treated as json, or post('/recommend/request', data=data, content_type='application/json'), i.e. pass the correct mime type

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question