Как получить сообщение от E11000 DuplicationKeyError? - PullRequest
0 голосов
/ 29 апреля 2020

Итак, я пишу юнит-тесты для проекта и тестирую register() функцию.

Вот она:

def register():
    # Get information about user
    username = request.get_json().get("username")
    password = request.get_json().get("password")
    name = request.get_json().get("name")
    email = request.get_json().get("email")

    # Put information about user in a tuple
    values = (
        None, 
        username, 
        User.hash_password(password), 
        name,
        email,
        None
    )

    try:
        # Create user and update session
        User(*values).create()
        ActiveUser.logged_in = True
        ActiveUser.username = username
        info_log.info("User %s registered successfully." % username)

        return jsonify(success=True, message="Registration successful!")

    except pymongo.errors.DuplicateKeyError as e:
        # Catch pymongo exception
        return jsonify(success=False, message="Duplicated username or email!"), 403

Я хочу иметь три теста: действительный, недействительный ( повторяющееся имя пользователя), недействительно (дубликаты электронной почты).

# Register helper function
def register(self, username, password, name, email):
    return self.app.post(
        "/register",
        data = json.dumps(dict(username = username, password = password, name = name, email = email)),
        content_type='application/json',
        follow_redirects = True
        )

def test_02_valid_user_registration(self):
    response = self.register('test', '12345678', 'Tester 1', 'test@mail.mail')
    self.assertEqual(response.status_code, 200)
    self.assertIn(b'Registration successful!', response.data)

def test_03_invalid_user_registration_duplicate_username(self):
    response = self.register('test', '12345678', 'Tester 2', 'test1@mail.mail')
    self.assertEqual(response.status_code, 403)
    self.assertIn(b'Duplicate username or email!', response.data)

def test_04_invalid_user_registration_duplicate_email(self):
    response = self.register('test2', '12345678', 'Tester 3', 'test@mail.mail')
    self.assertEqual(response.status_code, 403)
    self.assertIn(b'Duplicate username or email!', response.data)

Как и ожидалось, я получаю DuplicateKeyError, потому что я установил уникальный для этих параметров в базе данных.

pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: user.users index: username_1 dup key: { username: "test" }

Есть ли способ чтобы узнать, какой из элементов DuplicateKeyError является дублированным, поэтому у меня могут быть отдельные модульные тесты для дублирования имени пользователя и электронной почты?

Я знаю, что это скорее тестирование компонентов / интеграции, чем модульное тестирование, но это единственный способ, которым я знаю, как это сделать в Python 3.

1 Ответ

1 голос
/ 29 апреля 2020

Итак, я начал копаться в реализации DuplicateKeyError и обнаружил, что он содержит code и details.

Я напечатал details ошибки и получил это:

{
    "message": {
        "code": 11000,
        "errmsg": "E11000 duplicate key error collection: user.users index: username_1 dup key: { 
            username: \"test\" 
        }",
        "index": 0,
        "keyPattern": {
            "username": 1
        },
        "keyValue": {
            "username": "test"
        }
    },
    "success": false
}

После этого было легко заставить работать два теста.

try:
    # code
except pymongo.errors.DuplicateKeyError as e:
    # Catch pymongo exception
    key = list(e.details.get('keyValue').keys())[0]
    value = e.details.get('keyValue').get(key)
    return jsonify(success=False, message="Duplicate %s: %s" % (key, value)), 403

И тесты:

def test_03_invalid_user_registration_duplicate_username(self):
    response = self.register('test', '12345678', 'Tester 2', 'test1@mail.mail')
    self.assertEqual(response.status_code, 403)
    self.assertIn(b'Duplicate username: test', response.data)

def test_04_invalid_user_registration_duplicate_email(self):
    response = self.register('test', '12345678', 'Tester 3', 'test@mail.mail')
    self.assertEqual(response.status_code, 403)
    self.assertIn(b'Duplicate email: test@mail.mail', response.data)
...