#atomlib/atomtools.py
class AtomTools:
def __init__(self):
self.atomcachehelper = None
@property
def cache(self):
if not self.atomcachehelper:
from atomlib.AtomCacheHelper import AtomCacheHelper
self.atomcachehelper = AtomCacheHelper()
return self.atomcachehelper
# wdm_oms_failures_detector.py
import pandas as pd
from atomlib.atomtools import atomtools as atom
class WdmNetworkFailureDetector(object):
def __init__(self,):
self._cache_helper = atom.cache
def update_wdm_cache_data(self) -> pd.DataFrame:
df_oms = self._cache_helper.query_to_df()
return df_oms
# conftest.py
import pytest
@pytest.fixture(scope='module')
def df_oms():
path = 'some_path.csv'
df_oms = pd.read_csv(path)
return df_oms
# test_wdm_oms_failures_detector.py
from unittest.mock import patch, PropertyMock, call
from wdm_oms_failures_detector WdmNetworkFailureDetector
wnfd = WdmNetworkFailureDetector()
class TestWdmNetworkFailureDetector(object):
def test_get_mol_objects(self):
pass
@patch('wdm_oms_failures_detector.atom.cache')
def test_update_wdm_cache_data(self, mocked_cache, df_oms):
# Setup
mocked_cache.return_value.query_to_df.return_value = df_oms
# Exercise
wnfd.update_wdm_cache_data()
# Verify
mocked_cache.return_value.query_to_df.assert_called_once()
I am trying to patch WdmNetworkFailureDetector class' instance attribute atom.cache, which is a property of atomtools which returns and AtomCacheHelper object. Then I'd like to mock AtomCacheHelper's query_to_df method and return the fixture instead. I am not sure how to do it properly, I tried several ways, most of them resulted in the same AttributeErrors:
....
elif kwargs:
# can't set keyword args when we aren't creating the mock
# XXXX If new is a Mock we could call new.configure_mock(**kwargs)
raise TypeError("Can't pass kwargs to a mock we aren't creating")
new_attr = new
self.temp_original = original
self.is_local = local
> setattr(self.target, self.attribute, new_attr)
E AttributeError: can't set attribute
....
self = <unittest.mock._patch object at 0x000001E9B1618940>, exc_info = (<class 'AttributeError'>, AttributeError("can't set attribute",), <traceback object at 0x000001E9B17EEF48>)
def __exit__(self, *exc_info):
"""Undo the patch."""
if not _is_started(self):
raise RuntimeError('stop called on unstarted patcher')
if self.is_local and self.temp_original is not DEFAULT:
setattr(self.target, self.attribute, self.temp_original)
else:
> delattr(self.target, self.attribute)
E AttributeError: can't delete attribute
The problem is that you instantiate your tested class outside of the patching, so the cache helper is initialized with the real object, and patching it later does not change that, as it is already assigned to the variable. You have to do the instantiation during patching:
test_wdm_oms_failures_detector.py
from unittest.mock import patch
from wdm_oms_failures_detector import WdmNetworkFailureDetector
class TestWdmNetworkFailureDetector(object):
@patch('wdm_oms_failures_detector.atom.cache')
def test_update_wdm_cache_data(self, mocked_cache, df_oms):
mocked_cache.return_value.query_to_df.return_value = df_oms
wnfd = WdmNetworkFailureDetector() # now the cache helper is set to the mock
wnfd.update_wdm_cache_data()
mocked_cache.query_to_df.assert_called_once()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With