I'm working on a project that uses a class called Deck
to fetch data from an API. This class is instantiated inside another class called Game Manager
through its __init__
(it's a blackjack game btw) like this:
server/game_manager.py
import .deck import Deck
class GameManager:
self._deck = Deck()
server/deck.py
class Deck:
def fetch_cards(self):
'''Method that gets cards from api'''
pass
Right now I get an attribute not found
error that I can't get around when mocking Deck
class to avoid connecting to the API. My test goes in this way:
server/tests/game_manager_test.py
import unittest
from unittest.mock import patch, Mock
from ..game_manager import *
gm = GameManager()
class TestCardDraw(unittest.TestCase):
@patch("server.game_manager.deck")
def test_draw_game_start_cards(self, deck_mock):
deck_mock = Mock()
deck_mock.fetch_cards.return_value = [7,2]
self.assertEqual(len(gm._game_state["player_one"]["cards"]), 2)
Attribute Error: module 'server.game_manager' does not the attribute 'deck'
I'd like to ask the community a couple of questions to understand what I'm doing wrong.
deck
module from server/game_manager.py or the module deck
from the module server/deck.py itself?GameManager
at the top of my test suites to test some methods from the same instance. I've changed a value of this instance in one of the test suites to get the result I wanted with setUp
. Should I mock fetch_cards
method for this instance I'm using for tests or should I keep my strategy of mocking for the specific tests I want to make. What's the difference between this two approaches?Lastly, I've followed the examples in the documentation as well as Stack Overflow answers all around but at this point I feel confused with understanding what to mock and how to mocking. It's always cool to get your answers in code but I'd like to see where are my knowledge gaps in my thought process.
Deck object needs to be patched in the context where it's used.
Since the GameManager
object is instantiated in your test module, that provides the context for the patch.
You must patch the _deck
attribute of the gm
object and configure the MagicMock
instance to return the list when the fetch_cards
method is called.
gm = GameManager()
class TestCardDraw(unittest.TestCase):
@patch.object(gm, "_deck")
def test_draw_game_start_cards(self, deck_mock):
deck_mock.configure_mock(**{'fetch_cards.return_value': [7, 2]})
#...
self.assertEqual(len(gm._game_state["player_one"]["cards"]), 2)