test(weaviate): patch the class's own module, not a fixed string path

The Weaviate component moved into lfx-bundles, so weaviate.py is now
reachable under several module identities (the lfx.components.weaviate
shim, lfx_bundles.weaviate.weaviate, and the runtime _lfx_ext.* copy).
On Python 3.10, unittest.mock resolves a dotted patch target via a
getattr walk that follows the shim's package alias to a *different*
module object than the one the imported class actually lives in, so
patching 'lfx.components.weaviate.weaviate.WeaviateVectorStore' missed
the object the component body reads -> 'WeaviateVectorStore called 0
times' when an earlier test in the group forced the alternate identity.

Resolve the module from the imported class (sys.modules[Cls.__module__])
and patch.object it directly, bypassing dotted-string resolution. Same
fix for AuthApiKey. Order/identity-independent on all Python versions.
This commit is contained in:
Eric Hare
2026-06-16 15:34:39 -07:00
parent 61a55e8b2c
commit 064069b6bb

View File

@ -7,12 +7,21 @@ network boundary (the v4 ``connect_*`` helpers and the store class) is mocked so
the migration logic runs in CI without a live Weaviate instance.
"""
import sys
from unittest.mock import MagicMock
import pytest
from lfx.components.weaviate.weaviate import WeaviateVectorStoreComponent
from lfx.schema.data import Data
# The component moved into lfx-bundles, so ``weaviate.py`` is reachable under several
# module identities (the ``lfx.components.weaviate.weaviate`` shim, the canonical
# ``lfx_bundles.weaviate.weaviate``, and the runtime ``_lfx_ext.*`` ext-loader copy).
# Patch on the module the imported class actually lives in: a fixed string target like
# "lfx.components.weaviate.weaviate.WeaviateVectorStore" misses (mock "called 0 times")
# when an earlier test in the suite causes the class to resolve to a different identity.
_WEAVIATE_MODULE = sys.modules[WeaviateVectorStoreComponent.__module__]
def test_initialization():
component = WeaviateVectorStoreComponent()
@ -49,7 +58,7 @@ def test_connect_client_custom(mocker):
def test_connect_client_cloud(mocker):
"""A Weaviate Cloud URL routes to connect_to_weaviate_cloud (gRPC resolved internally)."""
mock_cloud = mocker.patch("weaviate.connect_to_weaviate_cloud", return_value=MagicMock())
mock_auth = mocker.patch("lfx.components.weaviate.weaviate.AuthApiKey", return_value="AUTH")
mock_auth = mocker.patch.object(_WEAVIATE_MODULE, "AuthApiKey", return_value="AUTH")
component = WeaviateVectorStoreComponent(
url="https://my-cluster.weaviate.network",
index_name="Test",
@ -74,7 +83,7 @@ def test_connect_client_wraps_errors(mocker):
def test_build_vector_store_without_documents(mocker):
mock_client = MagicMock()
mocker.patch.object(WeaviateVectorStoreComponent, "_connect_client", return_value=mock_client)
mock_store_cls = mocker.patch("lfx.components.weaviate.weaviate.WeaviateVectorStore", return_value=MagicMock())
mock_store_cls = mocker.patch.object(_WEAVIATE_MODULE, "WeaviateVectorStore", return_value=MagicMock())
fake_embedding = MagicMock()
component = WeaviateVectorStoreComponent(url="http://localhost:8080", index_name="Test")
@ -95,7 +104,7 @@ def test_build_vector_store_without_documents(mocker):
def test_build_vector_store_with_documents_uses_from_documents(mocker):
mock_client = MagicMock()
mocker.patch.object(WeaviateVectorStoreComponent, "_connect_client", return_value=mock_client)
mock_store_cls = mocker.patch("lfx.components.weaviate.weaviate.WeaviateVectorStore")
mock_store_cls = mocker.patch.object(_WEAVIATE_MODULE, "WeaviateVectorStore")
fake_embedding = MagicMock()
component = WeaviateVectorStoreComponent(url="http://localhost:8080", index_name="Test")