I am writing unit tests for my trading bot and can not figure out why, when I call a method belonging to a mocked class object, the dataframe being passed inside the method call is not being altered as per method definition and/or not being altered at all.
import pytest
from unittest.mock import MagicMock
import technical_analysis_manager_dir
from bot import Bot
from testing.sample_data_manager import big_sample_dataframe
def test_get_close_candidates_nearest_open(big_sample_dataframe):
update_date = '2024-03-18 12:54:00.000' # This is the date of the row whose divergence open value is being
# updated, to ensure later rows will have a pair
evaluation_date = '2024-03-18 13:26:00.000' # This is the date of the row whose divergence open value is being
# evaluated
# Create a sample dataframe via big_sample_dataframe
symbol = 'symbol'
sample_data = {symbol: big_sample_dataframe}
# Set the 'is_divergence_open_candidate' value == 1, at the update date
# Learning: What is the syntax to access a pandas dataframe row+column value?
# Answer: First select the dataframe, for this use case it is: sample_data['symbol']. Next call the loc method
# with: .loc[] (label based indexing). Inside the .loc[] property, specify a row and column label. Note: in the
# use case below, we conditionally select the row where the ['Date'] == update_date
sample_data['symbol'].loc[sample_data['symbol']['Date'] == update_date, 'is_divergence_open_candidate'] = 1
"""
------------------
Attention: This is what is working
------------------
"""
# Create an instance of DivergenceCalculator
divergence_calculator_instance = technical_analysis_manager_dir.DivergenceCalculator()
# Call the get_close_candidates_nearest_open method
divergence_calculator_instance.get_close_candidates_nearest_open(sample_data['symbol'], row_number=-1)
"""
------------------
End of what is what is working
------------------
"""
"""
------------------
Attention: This is what did NOT work
------------------
"""
# Learning: Here the 'spec=' keyword informs the MagicMock class constructor which object is being mocked. It
# therefore defines which methods and attributes that the mocked object should have.
mocked_divergence_calculator = MagicMock(spec=technical_analysis_manager_dir.DivergenceCalculator)
# Configure the return value of the mocked method
mocked_divergence_calculator.get_close_candidates_nearest_open.return_value = sample_data['symbol']
# Call the get_open_candidate method
mocked_divergence_calculator.get_close_candidates_nearest_open(sample_data, row_number=-1)
"""
------------------
End of what did NOT work
------------------
"""
print(sample_data['symbol'].loc[sample_data['symbol']['Date']== update_date, 'is_divergence_open_candidate'])
# Select the row which contains the target date (for later test assertion)
evaluation_df = sample_data['symbol'].loc[sample_data['symbol']['Date'] == evaluation_date]
print(evaluation_df)
print(evaluation_df['paired_divergence_opens_id'].iloc[-1])
# Learning: Why do I need to specify [0] in the below iloc call (integer based indexing)
# Answer: Every call of the '.iloc' property requires an integer to specify the row and then column. Example
# syntax: df.iloc[1, 0] will access the second [1] row, of the first [0] column. In the below use case we specify
# the column by label, so we only need to specify the row by integer, i.e. [0]
assert evaluation_df['paired_divergence_opens_id'].iloc[-1] == 128
As per the code block you can see what I had tried (with MagicMock()). I do not understand why it failed :/