diff --git a/src/mesh/DualMeshManager.cpp b/src/mesh/DualMeshManager.cpp
index 3917866b401590d61e312bf9338f10f7eb9f8975..11f09ff2172dbd9ca02f88293a39de53323fda77 100644
--- a/src/mesh/DualMeshManager.cpp
+++ b/src/mesh/DualMeshManager.cpp
@@ -24,6 +24,7 @@ DualMeshManager::destroy()
   Assert(m_instance != nullptr, "DualMeshManager was not created!");
 
   if (m_instance->m_mesh_to_dual_mesh_map.size() > 0) {
+    // LCOV_EXCL_START
     std::stringstream error;
     error << ": some meshes are still registered\n";
     for (const auto& [key, parent_mesh] : m_instance->m_mesh_to_dual_mesh_map) {
@@ -31,6 +32,7 @@ DualMeshManager::destroy()
             << " dual mesh of " << rang::fgB::yellow << parent_mesh.get() << rang::style::reset << '\n';
     }
     throw UnexpectedError(error.str());
+    // LCOV_EXCL_STOP
   }
   delete m_instance;
   m_instance = nullptr;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index ecc4880c2a86b48f73ad73eec93578eeb06188ac..c635fde526cd1e55218b8a0f5c8e97e18de9204d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -65,12 +65,13 @@ add_executable (unit_tests
   test_CubeTransformation.cpp
   test_DataVariant.cpp
   test_Demangle.cpp
-  test_DualConnectivityManager.cpp
   test_DiscreteFunctionDescriptorP0.cpp
   test_DiscreteFunctionDescriptorP0Vector.cpp
   test_DiscreteFunctionType.cpp
   test_DiscreteFunctionUtils.cpp
   test_DoWhileProcessor.cpp
+  test_DualConnectivityManager.cpp
+  test_DualMeshManager.cpp
   test_EdgeIntegrator.cpp
   test_EigenvalueSolver.cpp
   test_EmbeddedData.cpp
diff --git a/tests/test_DualMeshManager.cpp b/tests/test_DualMeshManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6e24f7aa99e558ebfd5ed621244a4a99e073bf37
--- /dev/null
+++ b/tests/test_DualMeshManager.cpp
@@ -0,0 +1,99 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <MeshDataBaseForTests.hpp>
+#include <mesh/DualMeshManager.hpp>
+
+#include <mesh/Connectivity.hpp>
+#include <mesh/Mesh.hpp>
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("DualMeshManager", "[mesh]")
+{
+  using ConnectivityType = Connectivity<2>;
+  using MeshType         = Mesh<ConnectivityType>;
+
+  std::shared_ptr<const MeshType> mesh = MeshDataBaseForTests::get().hybrid2DMesh();
+
+  SECTION("diamond dual mesh access")
+  {
+    std::shared_ptr p_diamond_dual_mesh = DualMeshManager::instance().getDiamondDualMesh(mesh);
+
+    const auto ref_counter = p_diamond_dual_mesh.use_count();
+
+    {
+      std::shared_ptr p_diamond_dual_mesh2 = DualMeshManager::instance().getDiamondDualMesh(mesh);
+
+      REQUIRE(p_diamond_dual_mesh == p_diamond_dual_mesh2);
+      REQUIRE(p_diamond_dual_mesh.use_count() == ref_counter + 1);
+    }
+
+    REQUIRE(p_diamond_dual_mesh.use_count() == ref_counter);
+
+    DualMeshManager::instance().deleteMesh(mesh.get());
+    REQUIRE(p_diamond_dual_mesh.use_count() == ref_counter - 1);
+
+    // Can delete mesh from the list again. This means that no
+    // dual mesh associated with it is managed.
+    REQUIRE_NOTHROW(DualMeshManager::instance().deleteMesh(mesh.get()));
+    REQUIRE(p_diamond_dual_mesh.use_count() == ref_counter - 1);
+
+    // A new dual mesh is built
+    std::shared_ptr p_diamond_dual_mesh_rebuilt = DualMeshManager::instance().getDiamondDualMesh(mesh);
+    REQUIRE(p_diamond_dual_mesh != p_diamond_dual_mesh_rebuilt);
+    REQUIRE(p_diamond_dual_mesh.get() != p_diamond_dual_mesh_rebuilt.get());
+
+    // Exactly two references to the dual mesh. One here and
+    // one in the manager.
+    REQUIRE(p_diamond_dual_mesh_rebuilt.use_count() == 2);
+  }
+
+  SECTION("median dual mesh access")
+  {
+    std::shared_ptr p_median_dual_mesh = DualMeshManager::instance().getMedianDualMesh(mesh);
+
+    const auto ref_counter = p_median_dual_mesh.use_count();
+
+    {
+      std::shared_ptr p_median_dual_mesh2 = DualMeshManager::instance().getMedianDualMesh(mesh);
+
+      REQUIRE(p_median_dual_mesh == p_median_dual_mesh2);
+      REQUIRE(p_median_dual_mesh.use_count() == ref_counter + 1);
+    }
+
+    REQUIRE(p_median_dual_mesh.use_count() == ref_counter);
+
+    DualMeshManager::instance().deleteMesh(mesh.get());
+    REQUIRE(p_median_dual_mesh.use_count() == ref_counter - 1);
+
+    // Can delete mesh from the list again. This means that no
+    // dual mesh associated with it is managed.
+    REQUIRE_NOTHROW(DualMeshManager::instance().deleteMesh(mesh.get()));
+    REQUIRE(p_median_dual_mesh.use_count() == ref_counter - 1);
+
+    // A new dual mesh is built
+    std::shared_ptr p_median_dual_mesh_rebuilt = DualMeshManager::instance().getMedianDualMesh(mesh);
+    REQUIRE(p_median_dual_mesh != p_median_dual_mesh_rebuilt);
+    REQUIRE(p_median_dual_mesh.get() != p_median_dual_mesh_rebuilt.get());
+
+    // Exactly two references to the dual mesh. One here and
+    // one in the manager.
+    REQUIRE(p_median_dual_mesh_rebuilt.use_count() == 2);
+  }
+
+  SECTION("check multiple dual mesh using/freeing")
+  {
+    std::shared_ptr p_median_dual_mesh  = DualMeshManager::instance().getMedianDualMesh(mesh);
+    std::shared_ptr p_diamond_dual_mesh = DualMeshManager::instance().getDiamondDualMesh(mesh);
+
+    const auto median_ref_counter  = p_median_dual_mesh.use_count();
+    const auto diamond_ref_counter = p_diamond_dual_mesh.use_count();
+
+    REQUIRE(p_median_dual_mesh != p_diamond_dual_mesh);
+
+    REQUIRE_NOTHROW(DualMeshManager::instance().deleteMesh(mesh.get()));
+    REQUIRE(p_median_dual_mesh.use_count() == median_ref_counter - 1);
+    REQUIRE(p_diamond_dual_mesh.use_count() == diamond_ref_counter - 1);
+  }
+}