@@ -66,7 +66,6 @@ def __init__(self, prefix="predbat"):
6666 # Cache structures
6767 self .cached_values = {}
6868 self .inverter_details = {}
69- self .storage_modes = {}
7069 self .parallel_battery_count = {}
7170 self .max_charge_current = {}
7271 self .max_discharge_current = {}
@@ -778,6 +777,30 @@ def test_solis_activated_with_api_key():
778777 return failed
779778
780779
780+ def test_initialize_attribute_parity_with_mock ():
781+ """Every attribute MockSolisAPI stubs must also be set by the real SolisAPI.initialize().
782+
783+ MockSolisAPI replaces __init__ wholesale, so an attribute added to the mock but forgotten in
784+ the real initialize() passes every unit test here and then raises AttributeError against a
785+ live inverter — which is exactly how capacity_voltage_warned shipped broken in #4502.
786+ """
787+ failed = False
788+ # Attributes that exist only to drive the test harness and have no production counterpart.
789+ test_only = {"_test_now_utc_exact" , "log_messages" , "dashboard_items" , "read_and_write_cid_calls" , "set_storage_mode_calls" }
790+ component = _init_solis_component ({"solis_api_key" : "k" , "solis_api_secret" : "s" })
791+ if component is None :
792+ print ("ERROR: Solis should activate with api_key + api_secret" )
793+ return True
794+ mock_attrs = set (vars (MockSolisAPI ()).keys ()) - test_only
795+ missing = sorted (attr for attr in mock_attrs if not hasattr (component , attr ))
796+ if missing :
797+ print ("ERROR: SolisAPI.initialize() does not set attributes stubbed by MockSolisAPI: {}" .format (missing ))
798+ failed = True
799+ if not failed :
800+ print ("PASSED: SolisAPI.initialize() sets every attribute MockSolisAPI stubs" )
801+ return failed
802+
803+
781804def test_solis_activated_with_oauth_token ():
782805 """Solis activates in OAuth mode when auth_method=oauth + access_token are configured (no api_key)."""
783806 failed = False
@@ -1018,6 +1041,7 @@ def run_solis_tests(my_predbat):
10181041 failed |= test_solis_not_activated_without_credentials ()
10191042 failed |= test_solis_activated_with_api_key ()
10201043 failed |= test_solis_activated_with_oauth_token ()
1044+ failed |= test_initialize_attribute_parity_with_mock ()
10211045 failed |= asyncio .run (test_oauth_execute_request_refreshes_before_call ())
10221046 failed |= asyncio .run (test_oauth_endpoint_namespace_translation ())
10231047 failed |= asyncio .run (test_oauth_execute_request_aborts_when_token_missing ())
0 commit comments