diff --git a/src/mesh/MeshFaceBoundary.cpp b/src/mesh/MeshFaceBoundary.cpp
index 3690c5c0c614a844060fa4c266e75fdcea42e377..751bcf962ca9ce2b8f7e7e5eab240a1c4768bcfb 100644
--- a/src/mesh/MeshFaceBoundary.cpp
+++ b/src/mesh/MeshFaceBoundary.cpp
@@ -26,7 +26,18 @@ getMeshFaceBoundary(const Mesh<Connectivity<Dimension>>& mesh, const IBoundaryDe
   }
 
   std::ostringstream ost;
-  ost << "cannot find surface with name " << rang::fgB::red << boundary_descriptor << rang::style::reset;
+  ost << "cannot find surface with name " << rang::fgB::red << boundary_descriptor << rang::style::reset << '\n';
+  ost << "The mesh contains " << mesh.connectivity().template numberOfRefItemList<ItemType::face>()
+      << " face boundaries: ";
+  for (size_t i_ref_face_list = 0; i_ref_face_list < mesh.connectivity().template numberOfRefItemList<ItemType::face>();
+       ++i_ref_face_list) {
+    const auto& ref_face_list = mesh.connectivity().template refItemList<ItemType::face>(i_ref_face_list);
+    const RefId& ref          = ref_face_list.refId();
+    if (i_ref_face_list > 0) {
+      ost << ", ";
+    }
+    ost << rang::fgB::yellow << ref << rang::style::reset;
+  }
 
   throw NormalError(ost.str());
 }
diff --git a/src/mesh/MeshFaceBoundary.hpp b/src/mesh/MeshFaceBoundary.hpp
index a45108aa5893c798230f41e14a8cacb071c60c0b..7493e9cd46e4d434902e65116024bbd7b82f5069 100644
--- a/src/mesh/MeshFaceBoundary.hpp
+++ b/src/mesh/MeshFaceBoundary.hpp
@@ -39,8 +39,8 @@ class [[nodiscard]] MeshFaceBoundary   // clazy:exclude=copyable-polymorphic
   MeshFaceBoundary(const Mesh<Connectivity<Dimension>>& mesh, const RefFaceList& ref_face_list);
 
  public:
-  MeshFaceBoundary(const MeshFaceBoundary&) = default;
-  MeshFaceBoundary(MeshFaceBoundary &&)     = default;
+  MeshFaceBoundary(const MeshFaceBoundary&) = default;   // LCOV_EXCL_LINE
+  MeshFaceBoundary(MeshFaceBoundary &&)     = default;   // LCOV_EXCL_LINE
 
   MeshFaceBoundary()          = default;
   virtual ~MeshFaceBoundary() = default;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 52a41bcb69fc8181fce73b92059b49cf1cccf314..ede705d518895f33e40790818a5ea2ccb7099892 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -175,6 +175,7 @@ add_executable (mpi_unit_tests
   test_ItemArrayUtils.cpp
   test_ItemValue.cpp
   test_ItemValueUtils.cpp
+  test_MeshFaceBoundary.cpp
   test_Messenger.cpp
   test_OFStream.cpp
   test_Partitioner.cpp
diff --git a/tests/test_MeshFaceBoundary.cpp b/tests/test_MeshFaceBoundary.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5b390e17f6b56001cb9abd119eeb8486a97b6dff
--- /dev/null
+++ b/tests/test_MeshFaceBoundary.cpp
@@ -0,0 +1,220 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <MeshDataBaseForTests.hpp>
+
+#include <mesh/Connectivity.hpp>
+#include <mesh/Mesh.hpp>
+#include <mesh/MeshFaceBoundary.hpp>
+#include <mesh/NamedBoundaryDescriptor.hpp>
+#include <mesh/NumberedBoundaryDescriptor.hpp>
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("MeshFaceBoundary", "[mesh]")
+{
+  auto is_same = [](const auto& a, const auto& b) -> bool {
+    if (a.size() > 0 and b.size() > 0) {
+      return (a[0] == b[0]);
+    } else {
+      return (a.size() == b.size());
+    }
+  };
+
+  SECTION("1D")
+  {
+    static constexpr size_t Dimension = 1;
+
+    using ConnectivityType = Connectivity<Dimension>;
+    using MeshType         = Mesh<ConnectivityType>;
+
+    SECTION("cartesian 1d")
+    {
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian1DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      const ConnectivityType& connectivity = mesh.connectivity();
+
+      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
+        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
+        const RefId ref_id        = ref_face_list.refId();
+
+        {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+
+        {
+          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+      }
+    }
+
+    SECTION("unordered 1d")
+    {
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().unordered1DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      const ConnectivityType& connectivity = mesh.connectivity();
+
+      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
+        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
+        const RefId ref_id        = ref_face_list.refId();
+
+        {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+
+        {
+          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+      }
+    }
+  }
+
+  SECTION("2D")
+  {
+    static constexpr size_t Dimension = 2;
+
+    using ConnectivityType = Connectivity<Dimension>;
+    using MeshType         = Mesh<ConnectivityType>;
+
+    SECTION("cartesian 2d")
+    {
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian2DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      const ConnectivityType& connectivity = mesh.connectivity();
+
+      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
+        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
+        const RefId ref_id        = ref_face_list.refId();
+
+        {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+
+        {
+          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+      }
+    }
+
+    SECTION("hybrid 2d")
+    {
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid2DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      const ConnectivityType& connectivity = mesh.connectivity();
+
+      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
+        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
+        const RefId ref_id        = ref_face_list.refId();
+
+        {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+
+        {
+          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+      }
+    }
+  }
+
+  SECTION("3D")
+  {
+    static constexpr size_t Dimension = 3;
+
+    using ConnectivityType = Connectivity<Dimension>;
+    using MeshType         = Mesh<ConnectivityType>;
+
+    SECTION("cartesian 3d")
+    {
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian3DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      const ConnectivityType& connectivity = mesh.connectivity();
+
+      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
+        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
+        const RefId ref_id        = ref_face_list.refId();
+
+        {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+          // force copy for tests
+          auto face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+
+        {
+          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+      }
+    }
+
+    SECTION("hybrid 3d")
+    {
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid3DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      const ConnectivityType& connectivity = mesh.connectivity();
+
+      for (size_t i = 0; i < connectivity.numberOfRefItemList<ItemType::face>(); ++i) {
+        const auto& ref_face_list = connectivity.refItemList<ItemType::face>(i);
+        const RefId ref_id        = ref_face_list.refId();
+
+        {
+          NumberedBoundaryDescriptor numbered_boundary_descriptor(ref_id.tagNumber());
+          // force copy for tests
+          auto face_boundary = getMeshFaceBoundary(mesh, numbered_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+
+        {
+          NamedBoundaryDescriptor named_boundary_descriptor(ref_id.tagName());
+          const auto& face_boundary = getMeshFaceBoundary(mesh, named_boundary_descriptor);
+          REQUIRE(is_same(face_boundary.faceList(), ref_face_list.list()));
+        }
+      }
+    }
+  }
+
+  SECTION("errors")
+  {
+    SECTION("cannot find boundary")
+    {
+      static constexpr size_t Dimension = 3;
+
+      using ConnectivityType = Connectivity<Dimension>;
+      using MeshType         = Mesh<ConnectivityType>;
+
+      std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid3DMesh();
+      const MeshType& mesh   = *p_mesh;
+
+      NamedBoundaryDescriptor named_boundary_descriptor("invalid_boundary");
+
+      REQUIRE_THROWS_WITH(getMeshFaceBoundary(mesh, named_boundary_descriptor),
+                          "error: cannot find surface with name \"invalid_boundary\"\nThe mesh contains 8 face "
+                          "boundaries: XMIN(22), XMAX(23), ZMAX(24), ZMIN(25), YMAX(26), YMIN(27), INTERFACE1(55), "
+                          "INTERFACE2(56)");
+    }
+  }
+}