11from dataclasses import dataclass
22from typing import Dict , List
33
4+ import pytest
5+
46from feast import utils
57from feast .protos .feast .types .Value_pb2 import Value
68
@@ -17,7 +19,7 @@ class MockFeatureView:
1719 projection : MockFeatureViewProjection
1820
1921
20- def test_get_unique_entities ():
22+ def test_get_unique_entities_success ():
2123 entity_values = {
2224 "entity_1" : [Value (int64_val = 1 ), Value (int64_val = 2 ), Value (int64_val = 1 )],
2325 "entity_2" : [
@@ -41,9 +43,87 @@ def test_get_unique_entities():
4143 join_key_values = entity_values ,
4244 entity_name_to_join_key_map = entity_name_to_join_key_map ,
4345 )
44-
45- assert unique_entities == (
46+ expected_entities = (
4647 {"entity_1" : Value (int64_val = 1 ), "entity_2" : Value (string_val = "1" )},
4748 {"entity_1" : Value (int64_val = 2 ), "entity_2" : Value (string_val = "2" )},
4849 )
49- assert indexes == ([0 , 2 ], [1 ])
50+ expected_indexes = ([0 , 2 ], [1 ])
51+
52+ assert unique_entities == expected_entities
53+ assert indexes == expected_indexes
54+
55+
56+ def test_get_unique_entities_missing_join_key_success ():
57+ """
58+ Tests that _get_unique_entities raises a KeyError when a required join key is missing.
59+ """
60+ # Here, we omit the required key for "entity_1"
61+ entity_values = {
62+ "entity_2" : [
63+ Value (string_val = "1" ),
64+ Value (string_val = "2" ),
65+ Value (string_val = "1" ),
66+ ],
67+ }
68+
69+ entity_name_to_join_key_map = {"entity_1" : "entity_1" , "entity_2" : "entity_2" }
70+
71+ fv = MockFeatureView (
72+ name = "fv_1" ,
73+ entities = ["entity_1" , "entity_2" ],
74+ projection = MockFeatureViewProjection (join_key_map = {}),
75+ )
76+
77+ unique_entities , indexes = utils ._get_unique_entities (
78+ table = fv ,
79+ join_key_values = entity_values ,
80+ entity_name_to_join_key_map = entity_name_to_join_key_map ,
81+ )
82+ expected_entities = (
83+ {"entity_2" : Value (string_val = "1" )},
84+ {"entity_2" : Value (string_val = "2" )},
85+ )
86+ expected_indexes = ([0 , 2 ], [1 ])
87+
88+ assert unique_entities == expected_entities
89+ assert indexes == expected_indexes
90+ # We're not say anything about the entity_1 missing from the unique_entities list
91+ assert "entity_1" not in [entity .keys () for entity in unique_entities ]
92+
93+
94+ def test_get_unique_entities_missing_all_join_keys_error ():
95+ """
96+ Tests that _get_unique_entities raises a KeyError when all required join keys are missing.
97+ """
98+ entity_values_not_in_feature_view = {
99+ "entity_3" : [Value (string_val = "3" )],
100+ }
101+ entity_name_to_join_key_map = {
102+ "entity_1" : "entity_1" ,
103+ "entity_2" : "entity_2" ,
104+ "entity_3" : "entity_3" ,
105+ }
106+
107+ fv = MockFeatureView (
108+ name = "fv_1" ,
109+ entities = ["entity_1" , "entity_2" ],
110+ projection = MockFeatureViewProjection (join_key_map = {}),
111+ )
112+
113+ with pytest .raises (KeyError ) as excinfo :
114+ utils ._get_unique_entities (
115+ table = fv ,
116+ join_key_values = entity_values_not_in_feature_view ,
117+ entity_name_to_join_key_map = entity_name_to_join_key_map ,
118+ )
119+
120+ error_message = str (excinfo .value )
121+ assert (
122+ "Missing join key values for keys: ['entity_1', 'entity_2', 'entity_3']"
123+ in error_message
124+ )
125+ assert (
126+ "No values provided for keys: ['entity_1', 'entity_2', 'entity_3']"
127+ in error_message
128+ )
129+ assert "Provided join_key_values: ['entity_3']" in error_message
0 commit comments