首页 > 解决方案 > 如何在不必模拟整个会话的情况下模拟 SQLALCHEMY 查询?

问题描述

我正在为我的应用程序中的一个函数编写一些单元测试,该函数充当我的 tictactoe 游戏的服务器。app.py 托管服务器,在其中,我有一个名为 on_winner 的函数。on_winner 基本上检查从客户端从套接字发出的用户名是赢家还是输家,它在数据库中查询他们的名字,更新他们的分数,然后将该数据推回数据库。

我只是在写一个单元测试来检查这个函数的逻辑。在我的测试功能中,我可以成功修补除 DB.session.query 之外的所有内容。我尝试使用谷歌搜索该主题,但我看到的许多示例都显示了带有 self 以外的参数的测试函数。我不确定我应该在这里写什么。

这是 app.py 中的函数:

def on_winner(data):
    """Tells everybody who'se won, and returns updated scores."""
    winner = DB.session.query(
        models.Person).filter_by(username=data['username'])
    if data['status'] == 'winner':
        winner.score += 1

    elif data['status'] == 'loser':
        winner.score -= 1

    DB.session.add(winner)
    DB.session.commit()
    ordered_scores = DB.session.query(models.Person).order_by(
        models.Person.score.desc())
    ordered_users = ordered_append(ordered_scores)
    #SOCKETIO.emit('winner', {'ordered_users': ordered_users},
     #             broadcast=True,
      #            include_self=True)
    return ordered_users

这是我的测试文件:

"""This file just tests that my app
correctly updates the score of winner
and loser"""
import unittest
from unittest.mock import patch
from app import on_winner
import models

INPUT = "user"
EXPECTED_OUTPUT = "expected"
USERNAME = 'username'
STATUS = 'status'
SCORE = 'score'
LETTER = 'letter'
class WinnerTestCase(unittest.TestCase):
    """Tests that the add_to_db function is working properly"""
    def setUp(self):
        self.success_test_params = [
            {
                INPUT:  {USERNAME : 'Kevin', STATUS : 'winner'},
                EXPECTED_OUTPUT: [{USERNAME : 'Joe', SCORE : 101, LETTER : 'O'}, {USERNAME : 'Kevin', SCORE : 101, LETTER : 'X'}, {USERNAME : 'Irene', SCORE : 100, LETTER : 'X'}]
            },
            {
                INPUT: {USERNAME : 'Irene', STATUS : 'loser'},
                EXPECTED_OUTPUT: [{USERNAME : 'Joe', SCORE : 101, LETTER : 'O'}, {USERNAME : 'Kevin', SCORE : 101, LETTER : 'X'}, {USERNAME : 'Irene', SCORE : 100, LETTER : 'X'}]
            },
            {
                INPUT : {USERNAME : 'Joe', STATUS : 'winner'},
                EXPECTED_OUTPUT: [{USERNAME : 'Joe', SCORE : 102, LETTER : 'O'}, {USERNAME : 'Kevin', SCORE : 101, LETTER : 'X'}, {USERNAME : 'Irene', SCORE : 100, LETTER : 'X'}]
            }
        ]
        KEVIN = models.Person(username='Kevin', score=100, letter='X')
        JOE = models.Person(username='Joe', score=101, letter='O')
        IRENE = models.Person(username='Irene', score=100, letter='X')
        self.initial_db_mock = [KEVIN, JOE, IRENE]
    def mocked_add(self, user):
        """Mocks db.session.add"""
    def mocked_commit(self):
        """Mocks db.session.commit"""
    def mocked_query(self,username):
        """Mocks query all"""
        print("You're in mocked_query")
        for person in self.initial_db_mock:
            if person[USERNAME]==username:
                return person
    def mocked_emit(self):
        """Mocks emit"""
    def ordered_mocked_query(self):
        """This function returns the list of users in descending order"""
        return sorted(self.initial_db_mock, key = lambda i : i[SCORE], reverse=True)
    def test_on_winner(self):
        """Tests the add functions. Mocks everything"""
        for test in self.success_test_params:
            with patch('app.DB.session.add', self.mocked_add):
                with patch('app.DB.session.commit', self.mocked_commit):
                    with patch('app.DB.session.query') as mocked_db_query:
                        #with patch('SOCKETIO.emit', self.mocked_emit):
                        mocked_db_query.filter_by.return_value = self.mocked_query
                        mocked_db_query.order_by.return_value = self.ordered_mocked_query
                        actual_result = on_winner(test[INPUT])
                        expected_result = test[EXPECTED_OUTPUT]
                        print (actual_result," ",expected_result)
                        self.assertEqual(len(actual_result), len(expected_result))
                        self.assertEqual(actual_result, expected_result)

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

标签: pythonunit-testingsqlalchemymocking

解决方案


推荐阅读