Skip to content

Commit

Permalink
SQlite for unit testing, depreciated methods replaced and unit tests …
Browse files Browse the repository at this point in the history
…for service layer (#2)

* test: create base test class

* feat: removed depreciated methods and fixed nested session issues

* test: setup sqlite, tests for management_service
  • Loading branch information
gabrielborgesdm committed May 19, 2024
1 parent 5a4b5e9 commit ba16206
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 14 deletions.
13 changes: 6 additions & 7 deletions backend/app/services/management_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@

class ManagementService:
def get_authors(self):
authors = AuthorModel.query.all()

authors = db.session.query(AuthorModel).all()
return authors_schema.dump(authors)

def get_books(self):
books = BookModel.query.all()

books = db.session.query(BookModel).all()
return books_schema.dump(books)

def create_author(self, author_data: Dict) -> AuthorSchema:
with db.session.begin():
with db.session.begin(True):
author = AuthorModel(**author_data)
db.session.add(author)
return author_schema.dump(author)

def create_book(self, book_dto: Dict):
with db.session.begin():
with db.session.begin(True):
authors = self._get_authors_for_book_creation(book_dto.get("authors"))

del book_dto["authors"]
book = BookModel(**book_dto)
book.authors = authors
Expand All @@ -47,7 +46,7 @@ def _find_or_create_author(
if existent_id is None:
return AuthorModel(**author_dto.get("authorCreationPayload"))

author = AuthorModel.query.get(existent_id)
author = db.session.get(AuthorModel, existent_id)
if author is None:
raise BadRequest(f"author of id {existent_id} was not found")

Expand Down
23 changes: 23 additions & 0 deletions backend/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import unittest
from flask import Flask

from backend.app.handlers.http_error_handler import handle_exception
Expand All @@ -13,6 +14,28 @@
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)

app.register_blueprint(books_bp)
app.register_blueprint(authors_bp)
app.register_error_handler(400, handle_exception)


class BaseTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.app = app
cls.app_context = cls.app.app_context()
cls.app_context.push()
cls.db = db

@classmethod
def tearDownClass(cls):
cls.app_context.pop()

def setUp(self):
self.db.session.close()
self.reset_db()

def reset_db(self):
self.db.drop_all()
self.db.create_all()
7 changes: 2 additions & 5 deletions backend/tests/controllers/test_book_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
from unittest.mock import patch

from backend.tests.conftest import app
from backend.tests.mocks.books_mock import (
book_create_with_invalid_author_mock,
book_create_with_existent_author_id_mock,
)
from backend.tests.mocks.books_mock import book_create_with_invalid_author_mock, book_create_mock


class TestGetBooks(unittest.TestCase):
Expand Down Expand Up @@ -48,7 +45,7 @@ def test_should_succeed(self, mock_create_book):
mock_create_book.return_value = books_mock_result

with app.test_client() as client:
response = client.post("/books/", json=book_create_with_existent_author_id_mock)
response = client.post("/books/", json=book_create_mock)

self.assertEqual(response.status_code, 201)

Expand Down
1 change: 1 addition & 0 deletions backend/tests/mocks/author_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"birthDate": "2001-01-01",
}


author_create_without_name_mock = {
"email": "email@test.com",
"nationality": "Brazil",
Expand Down
14 changes: 12 additions & 2 deletions backend/tests/mocks/books_mock.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
from backend.tests.mocks.author_mock import author_create_mock

book_create_with_invalid_author_mock = {
"title": "Aboovk",
"authors": [{"nonExistentProperty": "123"}],
"pages": 100,
}

book_create_with_existent_author_id_mock = {
book_create_mock = {
"title": "Aboovk",
"authors": [{"existentAuthorId": "123"}],
"authors": [{"authorCreationPayload": author_create_mock}],
"pages": 100,
}


def get_book_with_authors(authors):
return {
"title": "Aboovk",
"authors": authors,
"pages": 100,
}
9 changes: 9 additions & 0 deletions backend/tests/mocks/mock_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import copy


def get_mock_with_custom_args(mock_dict, **kwargs):
custom_mock = copy.deepcopy(mock_dict)
for key, value in kwargs.items():
custom_mock[key] = value

return custom_mock
Empty file.
71 changes: 71 additions & 0 deletions backend/tests/services/test_management_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from datetime import date
from backend.tests.conftest import BaseTestCase
from backend.tests.mocks.author_mock import author_create_mock, author_create_without_name_mock
from backend.tests.mocks.mock_utils import get_mock_with_custom_args
from backend.tests.mocks.books_mock import (
book_create_with_invalid_author_mock,
get_book_with_authors,
)

from backend.app.services.management_service import ManagementService

management_service = ManagementService()

author_mock = get_mock_with_custom_args(author_create_mock, birthDate=date.today())
book_mock = get_book_with_authors([{"authorCreationPayload": author_mock}])


class TestCreateBook(BaseTestCase):
def test_should_create_book_and_its_author(self):
self.assertEqual(len(management_service.get_authors()), 0)

book = management_service.create_book(book_mock)

self.assertEqual(len(management_service.get_authors()), 1)

self.assertEqual(book.get("title"), book_mock.get("title"))
self.assertEqual(book.get("pages"), book_mock.get("pages"))

def test_should_create_book_and_find_a_created_author(self):
self.assertEqual(len(management_service.get_authors()), 0)

author = management_service.create_author(author_mock)

self.assertIsNotNone(author.get("id"))
book = management_service.create_book(
get_book_with_authors([{"existentAuthorId": author.get("id")}])
)

self.assertEqual(len(management_service.get_authors()), 1)

self.assertEqual(book.get("title"), book_mock.get("title"))
self.assertEqual(book.get("pages"), book_mock.get("pages"))

def test_should_fail_when_book_does_not_have_required_field(self):
with self.assertRaises(Exception):
management_service.create_book(book_create_with_invalid_author_mock)


class TestCreateAuthor(BaseTestCase):
def test_should_create_author(self):
author = management_service.create_author(author_mock)
self.assertEqual(author.get("name"), author_mock.get("name"))
self.assertEqual(author.get("email"), author_mock.get("email"))

def test_should_fail_when_author_does_not_have_required_field(self):
with self.assertRaises(Exception):
management_service.create_author(author_create_without_name_mock)


class TestGetAuthors(BaseTestCase):
def test_count_should_start_being_zero(self):
authors = management_service.get_authors()
self.assertEqual(len(authors), 0)

def test_should_have_one_author_after_creation(self):

author = management_service.create_author(author_mock)

authors = management_service.get_authors()
self.assertEqual(len(authors), 1)
self.assertEqual(author.get("name"), authors[0].get("name"))

0 comments on commit ba16206

Please sign in to comment.