diff --git a/semantic_router/layer.py b/semantic_router/layer.py
index 222a5797a323171110820ce941df9d5803555cd6..4b7aa70d12f765a6c50030ba53f04fdaea88d215 100644
--- a/semantic_router/layer.py
+++ b/semantic_router/layer.py
@@ -204,10 +204,13 @@ class RouteLayer:
             if text is None:
                 raise ValueError("Either text or vector must be provided")
             vector = self._encode(text=text)
+        else:
+            vector = np.array(vector)
         # get relevant utterances
         results = self._retrieve(xq=vector)
         # decide most relevant routes
         top_class, top_class_scores = self._semantic_classify(results)
+        # TODO do we need this check?
         route = self.check_for_matching_routes(top_class)
         if route is None:
             return RouteChoice()
@@ -218,6 +221,10 @@ class RouteLayer:
         )
         passed = self._pass_threshold(top_class_scores, threshold)
         if passed:
+            if route.function_schema and text is None:
+                raise ValueError(
+                    "Route has a function schema, but no text was provided."
+                )
             if route.function_schema and not isinstance(route.llm, BaseLLM):
                 if not self.llm:
                     logger.warning(
@@ -228,10 +235,6 @@ class RouteLayer:
 
                     self.llm = OpenAILLM()
                     route.llm = self.llm
-                elif text is None:
-                    raise ValueError(
-                        "Text must be provided to use dynamic route with function_schema"
-                    )
                 else:
                     route.llm = self.llm
             return route(text)
@@ -382,7 +385,7 @@ class RouteLayer:
         config = self.to_config()
         config.to_file(file_path)
 
-    def get_route_thresholds(self) -> Dict[str, float]:
+    def get_thresholds(self) -> Dict[str, float]:
         # TODO: float() below is hacky fix for lint, fix this with new type?
         thresholds = {
             route.name: float(route.score_threshold or self.score_threshold)
@@ -400,7 +403,7 @@ class RouteLayer:
         Xq: Any = np.array(self.encoder(X))
         # initial eval (we will iterate from here)
         best_acc = self._vec_evaluate(Xq=Xq, y=y)
-        best_thresholds = self.get_route_thresholds()
+        best_thresholds = self.get_thresholds()
         # begin fit
         for _ in (pbar := tqdm(range(max_iter))):
             pbar.set_postfix({"acc": round(best_acc, 2)})
@@ -447,7 +450,7 @@ def threshold_random_search(
 ) -> Dict[str, float]:
     """Performs a random search iteration given a route layer and a search range."""
     # extract the route names
-    routes = route_layer.get_route_thresholds()
+    routes = route_layer.get_thresholds()
     route_names = list(routes.keys())
     route_thresholds = list(routes.values())
     # generate search range for each
diff --git a/tests/unit/test_layer.py b/tests/unit/test_layer.py
index 6e2ac317000a20f10d45cd671227e4831057e2da..c3c47e3def19d00ad1e85a6b78512a01974f197e 100644
--- a/tests/unit/test_layer.py
+++ b/tests/unit/test_layer.py
@@ -95,8 +95,18 @@ def routes():
 @pytest.fixture
 def dynamic_routes():
     return [
-        Route(name="Route 1", utterances=["Hello", "Hi"], function_schema="test"),
-        Route(name="Route 2", utterances=["Goodbye", "Bye", "Au revoir"]),
+        Route(name="Route 1", utterances=["Hello", "Hi"], function_schema={"name": "test"}),
+        Route(name="Route 2", utterances=["Goodbye", "Bye", "Au revoir"], function_schema={"name": "test"}),
+    ]
+
+@pytest.fixture
+def test_data():
+    return [
+        ("What's your opinion on the current government?", "politics"),
+        ("what's the weather like today?", "chitchat"),
+        ("what is the Pythagorean theorem?", "mathematics"),
+        ("what is photosynthesis?", "biology"),
+        ("tell me an interesting fact", None)
     ]
 
 
@@ -124,10 +134,10 @@ class TestRouteLayer:
         route_layer_none = RouteLayer(encoder=None)
         assert route_layer_none.score_threshold == openai_encoder.score_threshold
 
-    def test_initialization_dynamic_route(self, cohere_encoder, openai_encoder):
-        route_layer_cohere = RouteLayer(encoder=cohere_encoder)
+    def test_initialization_dynamic_route(self, cohere_encoder, openai_encoder, dynamic_routes):
+        route_layer_cohere = RouteLayer(encoder=cohere_encoder, routes=dynamic_routes)
         assert route_layer_cohere.score_threshold == 0.3
-        route_layer_openai = RouteLayer(encoder=openai_encoder)
+        route_layer_openai = RouteLayer(encoder=openai_encoder, routes=dynamic_routes)
         assert openai_encoder.score_threshold == 0.82
         assert route_layer_openai.score_threshold == 0.82
 
@@ -157,12 +167,23 @@ class TestRouteLayer:
 
     def test_query_and_classification(self, openai_encoder, routes):
         route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
-        query_result = route_layer("Hello").name
+        query_result = route_layer(text="Hello").name
         assert query_result in ["Route 1", "Route 2"]
 
     def test_query_with_no_index(self, openai_encoder):
         route_layer = RouteLayer(encoder=openai_encoder)
-        assert route_layer("Anything").name is None
+        assert route_layer(text="Anything").name is None
+    
+    def test_query_with_vector(self, openai_encoder, routes):
+        route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
+        vector = [0.1, 0.2, 0.3]
+        query_result = route_layer(vector=vector).name
+        assert query_result in ["Route 1", "Route 2"]
+
+    def test_query_with_no_text_or_vector(self, openai_encoder, routes):
+        route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
+        with pytest.raises(ValueError):
+            route_layer()
 
     def test_semantic_classify(self, openai_encoder, routes):
         route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
@@ -186,6 +207,12 @@ class TestRouteLayer:
         )
         assert classification == "Route 1"
         assert score == [0.9, 0.8]
+    
+    def test_query_no_text_dynamic_route(self, openai_encoder, dynamic_routes):
+        route_layer = RouteLayer(encoder=openai_encoder, routes=dynamic_routes)
+        vector = [0.1, 0.2, 0.3]
+        with pytest.raises(ValueError):
+            route_layer(vector=vector)
 
     def test_pass_threshold(self, openai_encoder):
         route_layer = RouteLayer(encoder=openai_encoder)
@@ -234,6 +261,24 @@ class TestRouteLayer:
         assert (route_layer_from_config.categories == route_layer.categories).all()
         assert route_layer_from_config.score_threshold == route_layer.score_threshold
 
+    def test_get_thresholds(self, openai_encoder, routes):
+        route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
+        assert route_layer.get_thresholds() == {'Route 1': 0.82, 'Route 2': 0.82}
+
+
+class TestLayerFit:
+    def test_eval(self, openai_encoder, routes, test_data):
+        route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
+        # unpack test data
+        X, y = zip(*test_data)
+        # evaluate
+        route_layer.evaluate(X=X, y=y)
+
+    def test_fit(self, openai_encoder, routes, test_data):
+        route_layer = RouteLayer(encoder=openai_encoder, routes=routes)
+        # unpack test data
+        X, y = zip(*test_data)
+        route_layer.fit(X=X, y=y)
 
 # Add more tests for edge cases and error handling as needed.