diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h
index 42d376698872e086c05a5905484e2f63c11dd346..771ca8c0859c3b462d5fbf6575e2e2569af2d61f 100644
--- a/include/caosdb/data_type.h
+++ b/include/caosdb/data_type.h
@@ -140,6 +140,21 @@ protected:
 
 class DataType : public ScalarProtoMessageWrapper<ProtoDataType> {
 public:
+  /**
+   * Copy constructor.
+   */
+  inline DataType(const DataType &other)
+    : DataType(ProtoMessageWrapper<ProtoDataType>::CopyProtoMessage(other.wrapped)) {}
+
+  /**
+   * Move constructor.
+   */
+  inline DataType(DataType &&other) : DataType(other.wrapped) {
+    other.wrapped = nullptr;
+    other.list_data_type.reset();
+    other.reference_data_type.reset();
+  }
+
   DataType(ProtoDataType *wrapped) : ScalarProtoMessageWrapper<ProtoDataType>(wrapped) {}
   DataType() : ScalarProtoMessageWrapper<ProtoDataType>(static_cast<ProtoDataType *>(nullptr)) {}
   /**
@@ -166,6 +181,8 @@ public:
     }
   }
 
+  ~DataType() = default;
+
   inline static auto ListOf(const AtomicDataType &atomic_data_type) -> DataType {
     return DataType(atomic_data_type, true);
   }
@@ -227,6 +244,37 @@ public:
     return this->wrapped == other.wrapped;
   }
 
+  /**
+   * Copy assignment operator.
+   */
+  inline auto operator=(const DataType &other) -> DataType & {
+    if (this != &other) {
+      this->reference_data_type.reset();
+      this->list_data_type.reset();
+      if (other.wrapped != nullptr) {
+        this->wrapped = ProtoMessageWrapper<ProtoDataType>::CopyProtoMessage(other.wrapped);
+      } else {
+        this->wrapped = nullptr;
+      }
+    }
+    return *this;
+  }
+
+  /**
+   * Move assignment operator.
+   */
+  inline auto operator=(DataType &&other) -> DataType & {
+    if (this != &other) {
+      this->wrapped = other.wrapped;
+      other.wrapped = nullptr;
+      other.reference_data_type.reset();
+      this->reference_data_type.reset();
+      other.list_data_type.reset();
+      this->list_data_type.reset();
+    }
+    return *this;
+  }
+
   friend class Entity;
   friend class Property;
 
diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h
index 6de939c37f19d9419815dcb8b7001fd19050133f..0e34e43092652e05f495b3715dc337b9de6f6989 100644
--- a/include/caosdb/entity.h
+++ b/include/caosdb/entity.h
@@ -51,8 +51,8 @@
 #include <random>                                      // for mt19937, rand...
 #include <stdexcept>                                   // for out_of_range
 #include <string>                                      // for string, basic...
-#include <vector>                                      // for vector
 #include <utility>                                     // for move
+#include <vector>                                      // for vector
 
 namespace caosdb::entity {
 using boost::filesystem::exists;
@@ -187,6 +187,32 @@ public:
     return result.append(std::string("]\n"));
   }
 
+  /**
+   * Return true if the underlying Protobuf messages have the same
+   * serialization.
+   */
+  inline auto operator==(const RepeatedPtrFieldWrapper<T, P> &other) const noexcept -> bool {
+    if (this->wrapped != nullptr && other.wrapped != nullptr && this->size() == other.size()) {
+      for (int i = 0; i < this->size(); i++) {
+        if (this->wrapped->Get(i).SerializeAsString() !=
+            other.wrapped->Get(i).SerializeAsString()) {
+          return false;
+        }
+      }
+      return true;
+    }
+    // last chance for "true": both nullptr?
+    return this->wrapped == other.wrapped;
+  }
+
+  /**
+   * Return true if the underlying Protobuf messages have a different
+   * serialization.
+   */
+  inline auto operator!=(const RepeatedPtrFieldWrapper<T, P> &other) const noexcept -> bool {
+    return !(*this == other);
+  }
+
 protected:
   RepeatedPtrFieldWrapper() : ProtoMessageWrapper<RepeatedPtrField<P>>(){};
   explicit inline RepeatedPtrFieldWrapper(RepeatedPtrField<P> *wrapped)
@@ -337,15 +363,13 @@ private:
  */
 class Messages : public RepeatedPtrFieldWrapper<Message, ProtoMessage> {
 public:
-  ~Messages();
-
   friend class Entity;
   // TODO(fspreck) Same here.
   // friend class Parent;
   // friend class Property;
 
 private:
-  inline Messages() : RepeatedPtrFieldWrapper(){};
+  inline Messages() : RepeatedPtrFieldWrapper<Message, ProtoMessage>(){};
 };
 
 /**
@@ -359,6 +383,37 @@ class Parent : public ScalarProtoMessageWrapper<ProtoParent> {
 public:
   explicit inline Parent(ProtoParent *wrapped) : ScalarProtoMessageWrapper<ProtoParent>(wrapped){};
   Parent() : ScalarProtoMessageWrapper<ProtoParent>(){};
+  ~Parent() = default;
+
+  /**
+   * Copy constructor.
+   */
+  inline Parent(const Parent &other)
+    : Parent(ProtoMessageWrapper<ProtoParent>::CopyProtoMessage(other.wrapped)) {}
+
+  /**
+   * Move constructor.
+   */
+  inline Parent(Parent &&other) : Parent(other.wrapped) { other.wrapped = nullptr; }
+
+  /**
+   * Copy assignment operator.
+   */
+  inline auto operator=(const Parent &other) -> Parent & {
+    if (this != &other) {
+      this->wrapped->CopyFrom(*other.wrapped);
+    }
+    return *this;
+  }
+
+  /**
+   * Move assignment operator.
+   */
+  inline auto operator=(Parent &&other) -> Parent & {
+    this->wrapped = other.wrapped;
+    other.wrapped = nullptr;
+    return *this;
+  }
 
   /**
    * Return the id of the parent entity.
@@ -426,14 +481,13 @@ private:
  */
 class Parents : public RepeatedPtrFieldWrapper<Parent, ProtoParent> {
 public:
-  ~Parents() = default;
   friend class Entity;
 
 private:
-  inline Parents() : RepeatedPtrFieldWrapper(){};
+  inline Parents() : RepeatedPtrFieldWrapper<Parent, ProtoParent>(){};
   explicit inline Parents(
     ::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent> *wrapped)
-    : RepeatedPtrFieldWrapper(wrapped){};
+    : RepeatedPtrFieldWrapper<Parent, ProtoParent>(wrapped){};
 };
 
 /**
@@ -456,13 +510,10 @@ public:
   /**
    * Move constructor.
    */
-  inline Property(Property &&other) : Property() {
+  inline Property(Property &&other) : Property(other.wrapped) {
     CAOSDB_LOG_TRACE(logger_name) << "Property::Property(Property  &&) "
                                   << "- Move constructor";
-    this->wrapped = std::move(other.wrapped);
-    this->value.wrapped = this->wrapped->mutable_value();
-    this->data_type.wrapped = this->wrapped->mutable_data_type();
-
+    other.wrapped = nullptr;
     other.data_type.wrapped = nullptr;
     other.value.wrapped = nullptr;
   }
@@ -477,6 +528,8 @@ public:
     : ScalarProtoMessageWrapper<ProtoProperty>(), value(static_cast<ProtoValue *>(nullptr)),
       data_type(static_cast<ProtoDataType *>(nullptr)){};
 
+  ~Property() = default;
+
   /**
    * Return the id of this  property
    */
@@ -563,8 +616,12 @@ public:
     CAOSDB_LOG_TRACE(logger_name) << "Property::operator=(const Property &) "
                                   << "- Copy assignment operator";
     this->wrapped->CopyFrom(*other.wrapped);
-    this->value = Value(this->wrapped->mutable_value());
-    this->data_type = DataType(this->wrapped->mutable_data_type());
+
+    this->value.wrapped = (this->wrapped->has_value() ? this->wrapped->mutable_value()
+                                                      : static_cast<ProtoValue *>(nullptr));
+    this->data_type.wrapped =
+      (this->wrapped->has_data_type() ? this->wrapped->mutable_data_type()
+                                      : static_cast<ProtoDataType *>(nullptr));
     return *this;
   }
 
@@ -574,7 +631,8 @@ public:
   auto operator=(Property &&other) -> Property & {
     CAOSDB_LOG_TRACE(logger_name) << "Property::operator=(Property &&) "
                                   << "- Move assignment operator";
-    this->wrapped = std::move(other.wrapped);
+    this->wrapped = other.wrapped;
+    other.wrapped = nullptr;
     this->value = std::move(other.value);
     this->data_type = std::move(other.data_type);
     return *this;
@@ -606,7 +664,6 @@ private:
  */
 class Properties : public RepeatedPtrFieldWrapper<Property, ProtoProperty> {
 public:
-  ~Properties() = default;
   friend class Entity;
 
 private:
@@ -624,17 +681,23 @@ private:
  * Overview of the Constructors:
  *
  * <li> Entity() - Calls Entity(ProtoEntity *) with a fresh ProtoEntity
- * <li> Entity(Entity) - Copy constructor, calls Entity(ProtoEntity *) after copying wrapped
- * ProtoEntity of the original, then also copies all Messages. <li> Entity(ProtoEntity *) - The
- * workhorse of the constructors. Initializes everything and does not call other Entity
- * constructors. <li> Entity(EntityResponse *) - Constructor which is used by the Transaction class
- * to create an Entity from the server's response, calls Entity(ProtoEntity). <li> Entity(IdResponse
- * *) - Constructor which is used by the Transaction class to create an Entity from the servers's
- * response. calls Entity(), then moves the data to the wrapped ProtoEntity.
- *
+ * <li> Entity(const Entity&) - Copy constructor, calls Entity(ProtoEntity *) after
+ *   copying wrapped ProtoEntity of the original, then also copies all Messages.
+ * <li> Entity(ProtoEntity *) - The workhorse of the constructors. Initializes
+ *   everything and does not call other Entity constructors.
+ * <li> Entity(EntityResponse *) - Constructor which is used by the Transaction class
+ *   to create an Entity from the server's response, calls Entity(ProtoEntity).
+ * <li> Entity(IdResponse *) - Constructor which is used by the Transaction
+ *   class to create an Entity from the servers's response. calls Entity(),
+ *   then moves the data to the wrapped ProtoEntity.
+ * <li> Entity(Entity&&) - Move constructor, calls Entity(ProtoEntity *), then
+ *   moves the messages and resets the original,
  */
 class Entity : public ScalarProtoMessageWrapper<ProtoEntity> {
 public:
+  /**
+   * Copy constructor.
+   */
   inline Entity(const Entity &original)
     : Entity(ProtoMessageWrapper::CopyProtoMessage(original.wrapped)) {
     this->errors.wrapped->CopyFrom(*original.errors.wrapped);
@@ -671,6 +734,58 @@ public:
     parents.wrapped = this->wrapped->mutable_parents();
   };
 
+  ~Entity() = default;
+
+  /**
+   * Move constructor.
+   */
+  explicit inline Entity(Entity &&original) : Entity(original.wrapped) {
+    original.wrapped = nullptr;
+    original.value.wrapped = nullptr;
+    original.data_type.wrapped = nullptr;
+    original.properties.wrapped = nullptr;
+    original.parents.wrapped = nullptr;
+    this->errors = std::move(original.errors);
+    this->warnings = std::move(original.warnings);
+    this->infos = std::move(original.infos);
+  };
+
+  /**
+   * Move assignment operator.
+   */
+  auto operator=(Entity &&other) -> Entity & {
+    this->wrapped = other.wrapped;
+    other.wrapped = nullptr;
+    this->data_type = std::move(other.data_type);
+    this->value = std::move(other.value);
+    this->properties = std::move(other.properties);
+    this->parents = std::move(other.parents);
+    this->file_descriptor = std::move(other.file_descriptor);
+    this->errors = std::move(other.errors);
+    this->warnings = std::move(other.warnings);
+    this->infos = std::move(other.infos);
+    return *this;
+  }
+
+  /**
+   * Copy assignment operator.
+   */
+  auto operator=(const Entity &other) -> Entity & {
+    this->wrapped->CopyFrom(*other.wrapped);
+    this->data_type = other.data_type;
+    this->value = other.value;
+    this->properties = other.properties;
+    this->parents = other.parents;
+    this->file_descriptor.local_path = boost::filesystem::path(other.file_descriptor.local_path);
+    this->file_descriptor.file_transmission_id->CopyFrom(
+      *other.file_descriptor.file_transmission_id);
+    this->file_descriptor.wrapped->CopyFrom(*other.file_descriptor.wrapped);
+    this->errors = other.errors;
+    this->warnings = other.warnings;
+    this->infos = other.infos;
+    return *this;
+  }
+
   [[nodiscard]] inline auto GetId() const noexcept -> const std::string & {
     return this->wrapped->id();
   };
@@ -787,6 +902,15 @@ public:
     infos.Clear();
   }
 
+  /**
+   * Return true if the other entity is equal to to this entity.
+   *
+   * This method ignores the errors, warnings and info messages.
+   */
+  inline auto operator==(const Entity &other) const noexcept -> bool {
+    return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString();
+  }
+
 private:
   inline auto GetNextFileId() -> std::string {
     std::string str = "0123456789abcdef";
diff --git a/include/caosdb/file_transmission/file_reader.h b/include/caosdb/file_transmission/file_reader.h
index 67c1247fa97cc43e28064b4e0da81812f41b231a..5820c1e9294c76f0f777a6e7cfae9cde7ebf490f 100644
--- a/include/caosdb/file_transmission/file_reader.h
+++ b/include/caosdb/file_transmission/file_reader.h
@@ -52,6 +52,7 @@
 #include <boost/filesystem/fstream.hpp>    // for ifstream
 #include <boost/filesystem/operations.hpp> // for exists
 #include <boost/filesystem/path.hpp>       // for path
+#include <cstddef>                         // for size_t
 #include <fstream>                         // for ifstream, size_t
 #include <string>                          // for string
 
diff --git a/include/caosdb/protobuf_helper.h b/include/caosdb/protobuf_helper.h
index 4dfc11c396ded34db6bb2cbed2c938a5402dd7c7..63b2c54cdfaae5eef33705ac7074e11c1caf3653 100644
--- a/include/caosdb/protobuf_helper.h
+++ b/include/caosdb/protobuf_helper.h
@@ -70,11 +70,7 @@ public:
    * serialization.
    */
   inline auto operator!=(const ProtoMessageWrapper<P> &other) const noexcept -> bool {
-    if (this->wrapped != nullptr && other.wrapped != nullptr) {
-      return this->wrapped->SerializeAsString() != other.wrapped->SerializeAsString();
-    }
-    // only one is nullptr?
-    return this->wrapped != other.wrapped;
+    return !(*this == other);
   }
 
 protected:
diff --git a/requirements.txt b/requirements.txt
index 4bf95a29fc3c9d28931a25664c2456f22041be3f..76372a8dce89684cb0c5490ff3d5afa916ea2f9c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,28 +1,29 @@
 attrs==21.2.0
 bottle==0.12.19
-certifi==2021.5.30
+certifi==2021.10.8
 chardet==4.0.0
+charset-normalizer==2.0.7
 colorama==0.4.4
-conan==1.40.3
-deprecation==2.0.7
-distro==1.5.0
+conan==1.41.0
+deprecation==2.1.0
+distro==1.6.0
 fasteners==0.16.3
 future==0.18.2
-idna==2.10
+idna==3.2
 Jinja2==2.11.3
-jsonschema==3.2.0
+jsonschema==4.1.0
 MarkupSafe==2.0.1
 node-semver==0.6.1
-packaging==20.9
+packaging==21.0
 patch-ng==1.17.4
 pluginbase==1.0.1
-Pygments==2.9.0
+Pygments==2.10.0
 PyJWT==1.7.1
 pyparsing==2.4.7
 pyrsistent==0.18.0
-python-dateutil==2.8.1
+python-dateutil==2.8.2
 PyYAML==5.4.1
-requests==2.25.1
-six==1.15.0
-tqdm==4.61.1
-urllib3==1.25.11
+requests==2.26.0
+six==1.16.0
+tqdm==4.62.3
+urllib3==1.26.7
diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp
index bb73431e4af00ed1db48b8f87fa883db6f4f9b31..a3872e4cb2be380adca644b7c7a109c0fec2b3c2 100644
--- a/src/caosdb/entity.cpp
+++ b/src/caosdb/entity.cpp
@@ -38,8 +38,6 @@ using ProtoFileDescriptor = caosdb::entity::v1alpha1::FileDescriptor;
 using caosdb::utility::get_arena;
 using google::protobuf::Arena;
 
-Messages::~Messages() = default;
-
 // Parent /////////////////////////////////////////////////////////////////////
 
 auto Parent::SetName(const std::string &name) -> void { this->wrapped->set_name(name); }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index aefe6846d23f2cc3a145cbf6158101e7e1bb3df4..9cacb63b0f6b74368508df6920e2dc03db81a929 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -41,7 +41,7 @@ set(test_cases
 
 # special linting for tests
 set(_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS
-  "${_CMAKE_CXX_CLANG_TIDY_CHECKS},-cert-err58-cpp,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-owning-memory,-modernize-use-trailing-return-type,-google-readability-avoid-underscore-in-googletest-name,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-readability-function-cognitive-complexity,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes"
+  "${_CMAKE_CXX_CLANG_TIDY_CHECKS},-cert-err58-cpp,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-owning-memory,-modernize-use-trailing-return-type,-google-readability-avoid-underscore-in-googletest-name,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-readability-function-cognitive-complexity,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-clang-analyzer-cplusplus.Move"
 )
 
 # add special cmake functions for gtest
diff --git a/test/test_data_type.cpp b/test/test_data_type.cpp
index 78e5100f3ce984ece46918df4aca9ffb8f1d2522..b1e714d705b23dcaef6354e17cf94e411f1d8335 100644
--- a/test/test_data_type.cpp
+++ b/test/test_data_type.cpp
@@ -129,4 +129,54 @@ TEST(test_data_type, test_data_type_to_string) {
   EXPECT_EQ(data_type3.ToString(), "{\n \"atomicDataType\": \"ATOMIC_DATA_TYPE_INTEGER\"\n}\n");
 }
 
+TEST(test_data_type, data_type_copy_constructor) {
+  DataType data_type("person", true);
+  const auto dt_string = data_type.ToString();
+
+  // copy
+  const DataType copy_data_type(data_type); // NOLINT (explicit copy)
+  EXPECT_EQ(copy_data_type, data_type);
+  EXPECT_EQ(dt_string, copy_data_type.ToString());
+}
+
+TEST(test_data_type, data_type_move_constructor) {
+  DataType data_type("person", true);
+  const auto dt_string = data_type.ToString();
+
+  // copy for testing
+  const DataType copy_data_type(data_type);
+  // move
+  const DataType move_data_type(std::move(data_type)); // NOLINT
+  EXPECT_NE(data_type, copy_data_type);                // NOLINT
+  EXPECT_NE(data_type.ToString(), dt_string);          // NOLINT
+
+  EXPECT_EQ(copy_data_type, move_data_type);
+  EXPECT_EQ(move_data_type.ToString(), dt_string);
+}
+
+TEST(test_data_type, data_type_copy_assignment) {
+  DataType data_type("person", true);
+  const auto dt_string = data_type.ToString();
+
+  // copy
+  DataType copy_data_type = data_type; // NOLINT (explicit copy)
+  EXPECT_EQ(copy_data_type, data_type);
+  EXPECT_EQ(dt_string, copy_data_type.ToString());
+}
+
+TEST(test_data_type, data_type_move_assignment) {
+  DataType data_type("person", true);
+  const auto dt_string = data_type.ToString();
+
+  // copy for testing
+  const DataType copy_data_type(data_type);
+  // move
+  DataType move_data_type = std::move(data_type); // NOLINT
+  EXPECT_NE(data_type, copy_data_type);           // NOLINT
+  EXPECT_NE(data_type.ToString(), dt_string);     // NOLINT
+
+  EXPECT_EQ(copy_data_type, move_data_type);
+  EXPECT_EQ(move_data_type.ToString(), dt_string);
+}
+
 } // namespace caosdb::entity
diff --git a/test/test_entity.cpp b/test/test_entity.cpp
index de0206f8b547884b7ae438b3bd4873230b9128d8..f66ee3f7185ee594f8465adde2e59fba2b62a328 100644
--- a/test/test_entity.cpp
+++ b/test/test_entity.cpp
@@ -44,7 +44,11 @@ namespace caosdb::entity {
 using caosdb::entity::v1alpha1::IdResponse;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 using ProtoParent = caosdb::entity::v1alpha1::Parent;
+using ProtoProperty = caosdb::entity::v1alpha1::Property;
+using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType;
+using caosdb::entity::v1alpha1::EntityResponse;
 using caosdb::utility::get_arena;
+using ProtoEntityRole = caosdb::entity::v1alpha1::EntityRole;
 
 TEST(test_entity, test_parent_setters) {
   auto parent = Parent();
@@ -138,7 +142,128 @@ TEST(test_entity, test_append_property) {
   EXPECT_EQ(prop.GetDataType(), same_prop.GetDataType());
 }
 
-TEST(test_entity, test_property_copy_constructor) {
+TEST(test_entity, entity_copy_constructor) {
+  ProtoParent parent;
+  parent.set_description("the parent desc");
+  parent.set_id("the parent id");
+  parent.set_name("the parent name");
+  ProtoProperty property;
+  property.set_id("the-prop-id");
+  property.set_description("the prop-desc");
+  property.set_name("the-prop-name");
+  property.mutable_value()->mutable_list_values()->mutable_values()->Add()->set_double_value(25.5);
+  property.mutable_data_type()->mutable_list_data_type()->set_atomic_data_type(
+    ProtoAtomicDataType::ATOMIC_DATA_TYPE_DOUBLE);
+  EntityResponse entity_response;
+  entity_response.mutable_entity()->set_id("the-id");
+  entity_response.mutable_entity()->set_name("the-name");
+  entity_response.mutable_entity()->set_role(ProtoEntityRole::ENTITY_ROLE_RECORD);
+  entity_response.mutable_entity()->set_description("the description");
+  entity_response.mutable_entity()->set_unit("the-unit");
+  entity_response.mutable_entity()->mutable_value()->mutable_scalar_value()->set_string_value(
+    "the-value");
+  entity_response.mutable_entity()->mutable_version()->set_id("version-id");
+  entity_response.mutable_entity()->mutable_data_type()->mutable_reference_data_type()->set_name(
+    "refname");
+  entity_response.mutable_entity()->mutable_file_descriptor();
+  entity_response.mutable_entity()->mutable_properties()->Add()->CopyFrom(property);
+  entity_response.mutable_entity()->mutable_parents()->Add()->CopyFrom(parent);
+
+  Entity this_entity(&entity_response);
+  Entity copy_entity(this_entity);
+
+  EXPECT_EQ(this_entity, copy_entity);
+  EXPECT_EQ(this_entity.GetVersionId(), copy_entity.GetVersionId());
+  EXPECT_EQ(this_entity.GetValue(), copy_entity.GetValue());
+  EXPECT_EQ(this_entity.GetDataType(), copy_entity.GetDataType());
+  EXPECT_EQ(this_entity.GetId(), copy_entity.GetId());
+  EXPECT_EQ(this_entity.GetName(), copy_entity.GetName());
+  EXPECT_EQ(this_entity.GetDescription(), copy_entity.GetDescription());
+  EXPECT_EQ(this_entity.ToString(), copy_entity.ToString());
+  EXPECT_EQ(this_entity.GetErrors().ToString(), copy_entity.GetErrors().ToString());
+  EXPECT_EQ(this_entity.GetWarnings().ToString(), copy_entity.GetWarnings().ToString());
+  EXPECT_EQ(this_entity.GetInfos().ToString(), copy_entity.GetInfos().ToString());
+  EXPECT_EQ(this_entity.GetProperties(), copy_entity.GetProperties());
+
+  // change only description
+  this_entity.SetDescription("new description");
+  EXPECT_NE(this_entity, copy_entity);
+  EXPECT_EQ(this_entity.GetVersionId(), copy_entity.GetVersionId());
+  EXPECT_EQ(this_entity.GetValue(), copy_entity.GetValue());
+  EXPECT_EQ(this_entity.GetDataType(), copy_entity.GetDataType());
+  EXPECT_EQ(this_entity.GetId(), copy_entity.GetId());
+  EXPECT_EQ(this_entity.GetName(), copy_entity.GetName());
+  EXPECT_NE(this_entity.GetDescription(), copy_entity.GetDescription());
+  EXPECT_NE(this_entity.ToString(), copy_entity.ToString());
+}
+
+TEST(test_entity, entity_move_constructor) {
+  ProtoParent parent;
+  parent.set_description("the parent desc");
+  parent.set_id("the parent id");
+  parent.set_name("the parent name");
+  ProtoProperty property;
+  property.set_id("the-prop-id");
+  property.set_description("the prop-desc");
+  property.set_name("the-prop-name");
+  property.mutable_value()->mutable_list_values()->mutable_values()->Add()->set_double_value(25.5);
+  property.mutable_data_type()->mutable_list_data_type()->set_atomic_data_type(
+    ProtoAtomicDataType::ATOMIC_DATA_TYPE_DOUBLE);
+  EntityResponse entity_response;
+  entity_response.mutable_errors()->Add()->set_code(25);
+  entity_response.mutable_errors()->Mutable(0)->set_description("asdf");
+  entity_response.mutable_warnings()->Add()->set_code(23);
+  entity_response.mutable_warnings()->Mutable(0)->set_description("asdgsafdg");
+  entity_response.mutable_infos()->Add()->set_code(235);
+  entity_response.mutable_infos()->Mutable(0)->set_description("asdfsad");
+  entity_response.mutable_entity()->set_id("the-id");
+  entity_response.mutable_entity()->set_name("the-name");
+  entity_response.mutable_entity()->set_role(ProtoEntityRole::ENTITY_ROLE_RECORD);
+  entity_response.mutable_entity()->set_description("the description");
+  entity_response.mutable_entity()->set_unit("the-unit");
+  entity_response.mutable_entity()->mutable_value()->mutable_scalar_value()->set_string_value(
+    "the-value");
+  entity_response.mutable_entity()->mutable_version()->set_id("version-id");
+  entity_response.mutable_entity()->mutable_data_type()->mutable_reference_data_type()->set_name(
+    "refname");
+  entity_response.mutable_entity()->mutable_file_descriptor();
+  entity_response.mutable_entity()->mutable_properties()->Add()->CopyFrom(property);
+  entity_response.mutable_entity()->mutable_parents()->Add()->CopyFrom(parent);
+
+  Entity this_entity(&entity_response);
+  std::string original_string = this_entity.ToString();
+  Entity copy_entity(this_entity);
+  EXPECT_EQ(this_entity, copy_entity);
+
+  Entity move_entity(std::move(this_entity));
+  EXPECT_NE(this_entity, copy_entity); // NOLINT
+
+  EXPECT_EQ(move_entity, copy_entity);
+  EXPECT_EQ(move_entity.GetVersionId(), copy_entity.GetVersionId());
+  EXPECT_EQ(move_entity.GetValue(), copy_entity.GetValue());
+  EXPECT_EQ(move_entity.GetDataType(), copy_entity.GetDataType());
+  EXPECT_EQ(move_entity.GetId(), copy_entity.GetId());
+  EXPECT_EQ(move_entity.GetName(), copy_entity.GetName());
+  EXPECT_EQ(move_entity.GetDescription(), copy_entity.GetDescription());
+  EXPECT_EQ(move_entity.ToString(), copy_entity.ToString());
+  EXPECT_EQ(move_entity.GetErrors().ToString(), copy_entity.GetErrors().ToString());
+  EXPECT_EQ(move_entity.GetWarnings().ToString(), copy_entity.GetWarnings().ToString());
+  EXPECT_EQ(move_entity.GetInfos().ToString(), copy_entity.GetInfos().ToString());
+  EXPECT_EQ(move_entity.GetProperties(), copy_entity.GetProperties());
+
+  // change only description
+  move_entity.SetDescription("new description");
+  EXPECT_NE(move_entity, copy_entity);
+  EXPECT_EQ(move_entity.GetVersionId(), copy_entity.GetVersionId());
+  EXPECT_EQ(move_entity.GetValue(), copy_entity.GetValue());
+  EXPECT_EQ(move_entity.GetDataType(), copy_entity.GetDataType());
+  EXPECT_EQ(move_entity.GetId(), copy_entity.GetId());
+  EXPECT_EQ(move_entity.GetName(), copy_entity.GetName());
+  EXPECT_NE(move_entity.GetDescription(), copy_entity.GetDescription());
+  EXPECT_NE(move_entity.ToString(), copy_entity.ToString());
+}
+
+TEST(test_entity, property_copy_constructor) {
   Property prop;
   prop.SetName("prop_name");
   prop.SetId("prop_id");
@@ -158,7 +283,7 @@ TEST(test_entity, test_property_copy_constructor) {
   EXPECT_EQ(prop.GetDataType(), other_prop.GetDataType());
 }
 
-TEST(test_entity, test_property_copy_assignment) {
+TEST(test_entity, property_copy_assignment) {
   Property prop;
   prop.SetName("prop_name");
   prop.SetId("prop_id");
@@ -183,7 +308,7 @@ TEST(test_entity, test_property_copy_assignment) {
   EXPECT_EQ(other_prop.GetName(), "other_prop_name");
 }
 
-TEST(test_entity, test_property_move_assignment) {
+TEST(test_entity, property_move_assignment) {
   Property prop;
   prop.SetName("prop_name");
   prop.SetId("prop_id");
@@ -191,15 +316,18 @@ TEST(test_entity, test_property_move_assignment) {
   prop.SetValue("prop_value");
   prop.SetUnit("prop_unit");
   prop.SetDataType("prop_dtype");
+  const auto prop_string = prop.ToString();
 
   // we compare the moved one with this one
   const Property copy_prop(prop);
 
   Property other_prop = std::move(prop);
-  // EXPECT_NE(prop, copy_prop);  NOLINT
-  // EXPECT_NE(prop, other_prop);  NOLINT
-  // EXPECT_EQ(prop.ToString(), "{}"); NOLINT
+  EXPECT_NE(prop, copy_prop);              // NOLINT
+  EXPECT_NE(prop, other_prop);             // NOLINT
+  EXPECT_NE(prop.ToString(), prop_string); // NOLINT
 
+  EXPECT_EQ(copy_prop.ToString(), prop_string);
+  EXPECT_EQ(other_prop.ToString(), prop_string);
   EXPECT_EQ(copy_prop, other_prop);
   EXPECT_EQ(copy_prop.GetName(), other_prop.GetName());
   EXPECT_EQ(copy_prop.GetId(), other_prop.GetId());
@@ -215,6 +343,127 @@ TEST(test_entity, test_property_move_assignment) {
   EXPECT_EQ(other_prop.GetName(), "other_prop_name");
 }
 
+TEST(test_entity, property_move_constructor) {
+  Property prop;
+  prop.SetName("prop_name");
+  prop.SetId("prop_id");
+  prop.SetImportance(Importance::RECOMMENDED);
+  prop.SetValue("prop_value");
+  prop.SetUnit("prop_unit");
+  prop.SetDataType("prop_dtype");
+  const auto prop_string = prop.ToString();
+
+  // we compare the moved one with this one
+  const Property copy_prop(prop);
+
+  Property other_prop(std::move(prop));
+  EXPECT_NE(prop, copy_prop);              // NOLINT
+  EXPECT_NE(prop, other_prop);             // NOLINT
+  EXPECT_NE(prop.ToString(), prop_string); // NOLINT
+
+  EXPECT_EQ(copy_prop.ToString(), prop_string);
+  EXPECT_EQ(other_prop.ToString(), prop_string);
+  EXPECT_EQ(copy_prop, other_prop);
+  EXPECT_EQ(copy_prop.GetName(), other_prop.GetName());
+  EXPECT_EQ(copy_prop.GetId(), other_prop.GetId());
+  EXPECT_EQ(copy_prop.GetImportance(), other_prop.GetImportance());
+  EXPECT_EQ(copy_prop.GetValue().ToString(), other_prop.GetValue().ToString());
+  EXPECT_EQ(copy_prop.GetUnit(), other_prop.GetUnit());
+  EXPECT_EQ(copy_prop.GetDataType(), other_prop.GetDataType());
+
+  other_prop.SetName("other_prop_name");
+  EXPECT_NE(copy_prop, other_prop);
+  EXPECT_NE(copy_prop.GetName(), other_prop.GetName());
+  EXPECT_EQ(copy_prop.GetName(), "prop_name");
+  EXPECT_EQ(other_prop.GetName(), "other_prop_name");
+}
+
+TEST(test_entity, parent_copy_constructor) {
+  Parent parent;
+  parent.SetId("par_id");
+  parent.SetName("par_name");
+
+  // copy
+  const Parent copy_parent(parent);
+  EXPECT_EQ(copy_parent, parent);
+  EXPECT_EQ(copy_parent.GetId(), parent.GetId());
+  EXPECT_EQ(copy_parent.GetName(), parent.GetName());
+
+  // change something
+  parent.SetName("new_name");
+  EXPECT_NE(copy_parent, parent);
+  EXPECT_EQ(copy_parent.GetId(), parent.GetId());
+  EXPECT_NE(copy_parent.GetName(), parent.GetName());
+}
+
+TEST(test_entity, parent_move_constructor) {
+  Parent parent;
+  parent.SetId("par_id");
+  parent.SetName("par_name");
+  const auto parent_string = parent.ToString();
+
+  // copy for testing
+  const Parent copy_parent = parent;
+  // move
+  Parent move_parent(std::move(parent));
+  EXPECT_NE(parent, copy_parent);              // NOLINT
+  EXPECT_NE(parent, move_parent);              // NOLINT
+  EXPECT_NE(parent.ToString(), parent_string); // NOLINT
+
+  EXPECT_EQ(copy_parent, move_parent);
+  EXPECT_EQ(copy_parent.GetId(), move_parent.GetId());
+  EXPECT_EQ(copy_parent.GetName(), move_parent.GetName());
+
+  // change something
+  move_parent.SetName("new_name");
+  EXPECT_NE(copy_parent, move_parent);
+  EXPECT_EQ(copy_parent.GetId(), move_parent.GetId());
+  EXPECT_NE(copy_parent.GetName(), move_parent.GetName());
+}
+
+TEST(test_entity, parent_copy_assignment) {
+  Parent parent;
+  parent.SetId("par_id");
+  parent.SetName("par_name");
+
+  // copy
+  const Parent copy_parent = parent;
+  EXPECT_EQ(copy_parent, parent);
+  EXPECT_EQ(copy_parent.GetId(), parent.GetId());
+  EXPECT_EQ(copy_parent.GetName(), parent.GetName());
+
+  // change something
+  parent.SetName("new_name");
+  EXPECT_NE(copy_parent, parent);
+  EXPECT_EQ(copy_parent.GetId(), parent.GetId());
+  EXPECT_NE(copy_parent.GetName(), parent.GetName());
+}
+
+TEST(test_entity, parent_move_assignment) {
+  Parent parent;
+  parent.SetId("par_id");
+  parent.SetName("par_name");
+  const auto parent_string = parent.ToString();
+
+  // copy for testing
+  const Parent copy_parent = parent;
+  // move
+  Parent move_parent = std::move(parent);
+  EXPECT_NE(parent, copy_parent);              // NOLINT
+  EXPECT_NE(parent, move_parent);              // NOLINT
+  EXPECT_NE(parent.ToString(), parent_string); // NOLINT
+
+  EXPECT_EQ(copy_parent, move_parent);
+  EXPECT_EQ(copy_parent.GetId(), move_parent.GetId());
+  EXPECT_EQ(copy_parent.GetName(), move_parent.GetName());
+
+  // change something
+  move_parent.SetName("new_name");
+  EXPECT_NE(copy_parent, move_parent);
+  EXPECT_EQ(copy_parent.GetId(), move_parent.GetId());
+  EXPECT_NE(copy_parent.GetName(), move_parent.GetName());
+}
+
 TEST(test_entity, test_copy_to) {
   auto entity = Entity();
   entity.SetRole(Role::RECORD);
@@ -565,6 +814,35 @@ TEST(test_entity, test_add_file) {
   EXPECT_EQ(entity.SetLocalPath(TEST_DATA_DIR + "/test.json"), StatusCode::SUCCESS);
 }
 
+TEST(test_entity, entity_move_assignment) {
+  Entity entity1;
+  entity1.SetRole(Role::RECORD_TYPE);
+  entity1.SetName("E1");
+  entity1.SetValue("some-string-1");
+  entity1.SetDataType("some-other-string-1");
+
+  Entity entity2;
+  entity1.SetRole(Role::RECORD);
+  entity1.SetName("E2");
+  entity1.SetValue("some-string-2");
+  entity1.SetDataType("some-other-string-2");
+
+  const Entity copy1(entity1); // NOLINT
+  const Entity copy2(entity2); // NOLINT
+
+  EXPECT_EQ(copy1, entity1);
+  EXPECT_EQ(copy2, entity2);
+
+  // Swap
+  Entity tmp;
+  tmp = std::move(entity1);
+  entity1 = std::move(entity2);
+  entity2 = std::move(tmp);
+
+  EXPECT_EQ(copy2, entity1);
+  EXPECT_EQ(copy1, entity2);
+}
+
 TEST(test_entity, test_entity_to_string) {
   Entity entity;
   EXPECT_EQ(entity.ToString(), "{}\n");
@@ -600,8 +878,8 @@ TEST(test_entity, test_property_to_string) {
   EXPECT_EQ(property.ToString(), "{}\n");
 
   property.SetDataType(AtomicDataType::DOUBLE);
-  EXPECT_EQ(property.ToString(),
-            "{\n \"dataType\": {\n  \"atomicDataType\": \"ATOMIC_DATA_TYPE_DOUBLE\"\n }\n}\n");
+  EXPECT_EQ(property.ToString(), "{\n \"dataType\": {\n  \"atomicDataType\": "
+                                 "\"ATOMIC_DATA_TYPE_DOUBLE\"\n }\n}\n");
 }
 
 TEST(test_entity, test_parents_to_string) {
diff --git a/test/test_value.cpp b/test/test_value.cpp
index 241f2bd0ce2a7291184a79cdaa0612f2b99fa204..ecf87d01f816048ebce95a0f63262a38fe8c8244 100644
--- a/test/test_value.cpp
+++ b/test/test_value.cpp
@@ -188,9 +188,9 @@ TEST(test_value, test_value_to_string) {
   EXPECT_EQ(value3.ToString(), "{\n \"scalarValue\": {\n  \"doubleValue\": 2.6\n }\n}\n");
 
   Value value4(std::vector<bool>{true, false});
-  EXPECT_EQ(value4.ToString(),
-            "{\n \"listValues\": {\n  \"values\": [\n   {\n    \"booleanValue\": true\n   },\n   "
-            "{\n    \"booleanValue\": false\n   }\n  ]\n }\n}\n");
+  EXPECT_EQ(value4.ToString(), "{\n \"listValues\": {\n  \"values\": [\n   {\n    "
+                               "\"booleanValue\": true\n   },\n   "
+                               "{\n    \"booleanValue\": false\n   }\n  ]\n }\n}\n");
 }
 
 } // namespace caosdb::entity