diff --git a/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp b/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp
index 4a14aa7fce29f5262f3d4eeb7080f2d6986c27f2..d7b5429947d56515f9c21fa32deb1c0fa59a81c4 100644
--- a/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp
+++ b/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp
@@ -20,7 +20,9 @@
  *             GNU General Public License
  */
 
+#include "ArmarXCore/core/exceptions/LocalException.h"
 #include <RobotAPI/interface/armem/query.h>
+#include <boost/test/tools/old/interface.hpp>
 #define BOOST_TEST_MODULE RobotAPI::ArmarXLibraries::armem
 
 #define ARMARX_BOOST_TEST
@@ -337,6 +339,11 @@ BOOST_AUTO_TEST_CASE(test_entity_BeforeTime_2)
 
 /* TimeApprox */
 
+/**
+ * @brief Lookup between elements. No range specified.
+ *
+ * Desired behavior: Return elements before and after timestamp.
+ */
 BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_no_limit)
 {
     BOOST_REQUIRE_EQUAL(entity.size(), 5);
@@ -358,7 +365,11 @@ BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_no_limit)
 
 }
 
-
+/**
+ * @brief Lookup between elements. Range is OK.
+ *
+ * Desired behavior: Return elements before and after timestamp.
+ */
 BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_600)
 {
     BOOST_REQUIRE_EQUAL(entity.size(), 5);
@@ -380,7 +391,11 @@ BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_600)
 
 }
 
-
+/**
+ * @brief Lookup between elements. Range is too small.
+ *
+ * Desired behavior: Return empty list.
+ */
 BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_too_small)
 {
     BOOST_REQUIRE_EQUAL(entity.size(), 5);
@@ -395,7 +410,11 @@ BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_too_small)
 
 }
 
-
+/**
+ * @brief Lookup between elements. Only next element is in range.
+ *
+ * Desired behavior: Return only element after query timestamp.
+ */
 BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_only_next)
 {
     BOOST_REQUIRE_EQUAL(entity.size(), 5);
@@ -414,9 +433,13 @@ BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_only_next)
 
         BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
     }
-
 }
 
+/**
+ * @brief Lookup between elements. Only previous element is in range.
+ *
+ * Desired behavior: Return only element before query timestamp.
+ */
 BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_only_previous)
 {
     BOOST_REQUIRE_EQUAL(entity.size(), 5);
@@ -435,7 +458,97 @@ BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_limit_only_previous)
 
         BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
     }
+}
+
+/**
+ * @brief Lookup with perfect match.
+ *
+ * Desired behavior: Return only element matching timestamp exactly.
+ */
+BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_perfect_match)
+{
+    BOOST_REQUIRE_EQUAL(entity.size(), 5);
+    addResults(query::entity::TimeApprox{ 3000, -1});
+    BOOST_REQUIRE_EQUAL(results.size(), 2);
+
+    for (const auto& result : results)
+    {
+        std::vector<armem::Time> times = simox::alg::get_keys(result.history());
+        BOOST_REQUIRE_EQUAL(times.size(), 1);
+
+        std::vector<armem::Time> expected
+        {
+            armem::Time::microSeconds(3000)
+        };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
 
+/**
+ * @brief Invalid lookup into the past.
+ *
+ * Desired behavior: Return empty list.
+ */
+BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_lookup_past)
+{
+    BOOST_REQUIRE_EQUAL(entity.size(), 5);
+    addResults(query::entity::TimeApprox{ 1, 1});
+    BOOST_REQUIRE_EQUAL(results.size(), 2);
+
+    for (const auto& result : results)
+    {
+        std::vector<armem::Time> times = simox::alg::get_keys(result.history());
+        BOOST_REQUIRE(times.empty());
+    }
+}
+
+/**
+ * @brief Invalid lookup into the future.
+ *
+ * Desired behavior: Return empty list.
+ */
+BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_lookup_future)
+{
+    BOOST_REQUIRE_EQUAL(entity.size(), 5);
+    addResults(query::entity::TimeApprox{ 10'000, 1});
+    BOOST_REQUIRE_EQUAL(results.size(), 2);
+
+    for (const auto& result : results)
+    {
+        std::vector<armem::Time> times = simox::alg::get_keys(result.history());
+        BOOST_REQUIRE(times.empty());
+    }
+}
+
+/**
+ * @brief Lookup into the future, but still considered valid as time range is not set.
+ *
+ * Desired behavior: Return most recent element in history.
+ */
+BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_lookup_future_valid)
+{
+    BOOST_REQUIRE_EQUAL(entity.size(), 5);
+    addResults(query::entity::TimeApprox{ 10'000, -1});
+    BOOST_REQUIRE_EQUAL(results.size(), 2);
+
+    for (const auto& result : results)
+    {
+        std::vector<armem::Time> times = simox::alg::get_keys(result.history());
+        BOOST_REQUIRE_EQUAL(times.size(), 1);
+
+        std::vector<armem::Time> expected
+        {
+            armem::Time::microSeconds(5'000)
+        };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS(times.begin(), times.end(), expected.begin(), expected.end());
+    }
+}
+
+BOOST_AUTO_TEST_CASE(test_entity_TimeApprox_lookup_invalid_timestamp)
+{
+    BOOST_REQUIRE_THROW(addResults(query::entity::TimeApprox{ -1, 1}), ::armarx::LocalException);
 }