Django Mock 数据库无法正常工作

问题描述 投票:0回答:1

我正在为 post 方法编写单元测试方法,但由于某种原因,它不断修改实际数据库而不是模拟数据库。 这是我的测试方法:

def test_post_contest(self):
    mock_collection = self.mock_db.collection.return_value
    mock_document = mock_collection.document.return_value

    mock_document.set.return_value = None

    response = self.client.post(
        reverse('contest-list'),
        data={
            'ONI2024F2': {
                'name': 'ONI2024F2', 
                'problems': ['problem1', 'problem2'],
                'administratorId': '0987654321'
            }
        },
        format='json'
    )
    self.assertEqual(response.status_code, 201)
    self.assertEqual(response.json(), {'id': 'ONI2024F2'})

这是setUp方法:

    def setUp(self):
        self.client = APIClient()
        self.mock_db = patch('firebase_config.db').start()
        self.addCleanup(patch.stopall)

这是 firebase_config.py 文件

import os
import firebase_admin
from firebase_admin import credentials, firestore

#Path to Firebase credentials
cred_path = os.path.join(os.path.dirname(__file__), 'credentials','firebase_credentials.json')

#Initialize Firebase
cred = credentials.Certificate(cred_path)
firebase_admin.initialize_app(cred)

#Firestore client
db = firestore.client()

这是整个测试文件:

from django.test import TestCase
from django.urls import reverse
from unittest.mock import patch, MagicMock
from rest_framework.test import APIClient

class ContestViewTest(TestCase):
    
    def setUp(self):
        self.client = APIClient()
        self.mock_db = patch('firebase_config.db').start()
        self.addCleanup(patch.stopall)

    @patch('OIECApp.views.ContestView.referenceToJson')
    def test_get_contest_list(self, mock_referenceToJson):
        mock_referenceToJson.return_value = {'name': 'ONI2024F1'}

        mock_collection = self.mock_db.collection.return_value
        mock_doc = MagicMock()
        mock_doc.id = 'ONI2024F1'
        mock_collection.stream.return_value = [mock_doc]

        response = self.client.get(reverse('contest-list'))

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {'IOI2023': {'name': 'ONI2024F1'}, 'ONI2024F1': {'name': 'ONI2024F1'}})

    def test_post_contest(self):
        mock_collection = self.mock_db.collection.return_value
        mock_document = mock_collection.document.return_value

        mock_document.set.return_value = None

        response = self.client.post(
            reverse('contest-list'),
            data={
                'ONI2024F2': {
                    'name': 'ONI2024F2', 
                    'problems': ['problem1', 'problem2'],
                    'administratorId': '0987654321'
                }
            },
            format='json'
        )
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.json(), {'id': 'ONI2024F2'})

    @patch('OIECApp.views.ContestView.referenceToJson')
    def test_get_contest_detail(self, mock_referenceToJson):
        mock_referenceToJson.return_value = {'name': 'ONI2024F1'}

        mock_collection = self.mock_db.collection.return_value
        mock_doc = MagicMock()
        mock_doc.id = 'ONI2024F1'
        mock_collection.stream.return_value = [mock_doc]

        response = self.client.get(reverse('contest-detail', args=['ONI2024F1']))

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {'ONI2024F1': {'name': 'ONI2024F1'}})

    def test_put_contest(self):
        mock_collection = self.mock_db.collection.return_value
        mock_document = mock_collection.document.return_value

        # Mock the update operation
        mock_document.update.return_value = None

        response = self.client.put(
            reverse('contest-detail', args=['ONI2025F1']),
            data={
                'ONI2025F1': {
                    'name': 'ONI2025F1',
                    'problems': ['problem1', 'problem3'],
                    'administratorId': '0987654321'
                }
            },
            format='json'
        )
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.json(), {'id': 'ONI2025F1'})

    def test_delete_contest(self):
        mock_collection = self.mock_db.collection.return_value
        mock_document = mock_collection.document.return_value

        # Mock the delete operation
        mock_document.delete.return_value = None

        response = self.client.delete(reverse('contest-detail', args=['ONI2024F2']))
        self.assertEqual(response.status_code, 204)

这是带有 http 方法的文件:

from django.http import Http404, JsonResponse
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from firebase_config import db
from firebase_admin import firestore

collection_name = "Contest"

def referenceToJson(element):
    doc_dict = element.to_dict()
    for x in doc_dict:
        tmp = doc_dict[x]
        if isinstance(tmp, list):
            counter = 0
            for y in tmp:
                if isinstance(y, firestore.firestore.DocumentReference):
                    doc_ref = y.get().id
                    tmp[counter]=doc_ref
                counter += 1
        else:
            if isinstance(tmp, firestore.firestore.DocumentReference):
                doc_ref = tmp.get().id
                doc_dict[x]=doc_ref
    return doc_dict

class ContestList(APIView):

    def get(self, request):
        contest_ref = db.collection(collection_name)
        contests = dict ()
        
        for doc in contest_ref.stream():
            idContest = doc.id
            doc_dict = referenceToJson(doc)
            contests[idContest]= doc_dict
        return JsonResponse(contests)
    
    def post(self, request):
        try: 
            datos = request.data
            clave = list(datos.keys())[0]
            valores = datos[clave]
            for c in valores.keys():
                if(c == 'Problems') or (c == 'problems'):
                    if isinstance(valores[c], list):
                        contador = 0
                        for element in valores[c]:
                            print(element)
                            ingreso = db.collection('Problems').document(valores[c][contador])
                            valores[c][contador]=ingreso
                            contador += 1
                    else:
                        ingreso = db.collection('Problems').document(valores[c])
                        valores[c] = ingreso
                elif(c == 'administratorId'):
                    ingreso = db.collection('Administrator').document(valores[c])
                    valores[c] = ingreso
            db.collection(collection_name).document(clave).set(valores)
            return JsonResponse({'id':clave}, status=201)
        except Exception as e:  
            return JsonResponse({'error':str(e)}, status=500)

class ContestDetail(APIView):

    def get(self, request, id):
        contest_ref = db.collection(collection_name)
        contest = dict ()
        
        for doc in contest_ref.stream():
            if(doc.id == id):
                idContest = doc.id
                doc_dict = referenceToJson(doc)
                contest[idContest] = doc_dict

        return JsonResponse(contest)

    def put(self,request,id):
        try: 
            datos = request.data
            clave = list(datos.keys())[0]
            valores = datos[clave]
            for c in valores.keys():
                if(c == 'Problems') or (c == 'problems'):
                    if isinstance(valores[c], list):
                        list_ref = []
                        for element in valores[c]:
                            ingreso = db.collection('Problems').document(element)
                            list_ref.append(ingreso)
                        valores[c] = list_ref
                    else:
                        ingreso = db.collection('Problems').document(valores[c])
                        valores[c] = ingreso
                elif(c == 'administratorId'):
                    ingreso = db.collection('Administrator').document(valores[c])
                    valores[c] = ingreso
            db.collection(collection_name).document(clave).update(valores)
            return JsonResponse({'id':clave}, status=201)
        except Exception as e:  
            return JsonResponse({'error':str(e)}, status=500)

    def delete(self, request, id):
        try:
            contest_ref = db.collection(collection_name).document(id)
            contest_ref.delete()
            return JsonResponse({'message': 'Deleted'}, status=204)
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)

我认为这可能是 firebase-config 文件,所以我尝试更改它,但随后所有测试都引发了异常。

python django unit-testing google-cloud-firestore firebase-admin
1个回答
0
投票

使用

from firebase_config import db
代替
import firebase_config
,并使用
firebase_config.db
引用数据库。

一旦您

from firebase_config import db
,您需要修补
my_module.db
而不是
firebase_config.db

但是,这是不可扩展的;您不想明确地修补每个用法。

© www.soinside.com 2019 - 2024. All rights reserved.