diff --git a/.docker/Dockerfile b/.docker/Dockerfile
index a0d975f82b721dd71cc1e4f7e724c47c20e28a55..98f12aabb4ddf22f9375c97669e025adaed6b627 100644
--- a/.docker/Dockerfile
+++ b/.docker/Dockerfile
@@ -7,7 +7,7 @@ COPY .docker/wait-for-it.sh /wait-for-it.sh
 WORKDIR /libcaosdb/
 RUN mkdir build
 WORKDIR /libcaosdb/build
-RUN conan create .. -s "compiler.libcxx=libstdc++11"
+RUN conan create -s "compiler.libcxx=libstdc++11" -o caosdb:build_acm=True .. "caosdb/$(conan inspect --raw version ..)@_/_"
 
 COPY . /caosdb-cppinttest
 WORKDIR /caosdb-cppinttest
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b885dc69cdd4ccc88069808590e2a82842ce8ad3..67840eb44a10ea3aa4ee850ee6a5f0108b33fb10 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -72,6 +72,10 @@ build-testenv: &build-testenv
   stage: setup
   timeout: 2h
   needs: []
+  only:
+    - pipelines
+    - schedules
+    - web
   script:
     - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
 
@@ -118,17 +122,21 @@ test:
     - job: build-test
   script:
     - echo $PWD
+    - F_BRANCH="${F_BRANCH:-$CI_COMMIT_REF_NAME}" ;
+    - echo "F_BRANCH = $F_BRANCH"
+    - echo "CAOSDB_TAG = $CAOSDB_TAG"
+    - echo "DEPLOY_REF = $DEPLOY_REF"
     - ls -la
 
     - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
 
-    - if [[ "$CAOSDB_TAG" == "" ]]; then
+    - if [ -z "$CAOSDB_TAG" ]; then
         if echo "$F_BRANCH" | grep -c "^f-" ; then
           CAOSDB_TAG=${DEPLOY_REF}_F_${F_BRANCH};
           docker pull $CI_REGISTRY/caosdb/src/caosdb-deploy:$CAOSDB_TAG || CAOSDB_TAG="${DEFAULT_CAOSDB_TAG}" ;
-        elif [ "$F_BRANCH" == "main" ] ; then
+        elif [ "$F_BRANCH" = "main" ] ; then
           CAOSDB_TAG=main ;
-        elif [ "$F_BRANCH" == "dev" ] ; then
+        elif [ "$F_BRANCH" = "dev" ] ; then
           CAOSDB_TAG=dev ;
         else
           CAOSDB_TAG="${DEFAULT_CAOSDB_TAG}" ;
diff --git a/conanfile.txt b/conanfile.txt
index 97af2de0f1426a8c30f3b9e7eb74460c35224978..6204fd13a0469bd0f0721d236e410c90cdcbbb2a 100644
--- a/conanfile.txt
+++ b/conanfile.txt
@@ -6,3 +6,6 @@ gtest/1.11.0
 
 [generators]
 cmake
+
+[options]
+caosdb:build_acm=True
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 347d0170ae23c71b1e140cbd1bb4c715d2042c83..0053aaadbf0e0124c1c30fabb7e6955d1f9b3a39 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -29,8 +29,10 @@ set(test_cases
     test_transaction
     test_ccaosdb
     test_issues
+    test_user
     )
 
+add_compile_definitions(BUILD_ACM)
 
 include(CheckCXXCompilerFlag)
 include(CheckCCompilerFlag)
diff --git a/test/caosdb_test_utility.h b/test/caosdb_test_utility.h
index 581e6038ffa961e9005f6e9f5e05d18e2205ee26..7c29f902d8bd0fa3308ff174ad8609820d67fa1f 100644
--- a/test/caosdb_test_utility.h
+++ b/test/caosdb_test_utility.h
@@ -45,4 +45,12 @@
       throw;                                                                                       \
     },                                                                                             \
     exeption_type)
+#define EXPECT_THROW_STARTS_WITH(statement, exception_type, pattern)                               \
+  EXPECT_THROW(                                                                                    \
+    try { statement; } catch (const exception_type &e) {                                           \
+      auto pat_s = std::string(pattern);                                                           \
+      EXPECT_EQ(std::string(e.what()).substr(0, pat_s.size()), pat_s);                             \
+      throw;                                                                                       \
+    },                                                                                             \
+    exception_type)
 #endif
diff --git a/test/test_user.cpp b/test/test_user.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d721686891d045bd0493770bf3d3a951c19fc6b
--- /dev/null
+++ b/test/test_user.cpp
@@ -0,0 +1,69 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2022 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2022 IndiScale GmbH <info@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#include "caosdb/acm/user.h"       // for User
+#include "caosdb/connection.h"     // for Connection, VersionInfo, path
+#include "caosdb/exceptions.h"     // for TransactionError
+#include "caosdb_test_utility.h"   // for EXPECT_THROW_MESSAGE
+#include <gtest/gtest-message.h>   // for Message
+#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestPartR...
+#include <gtest/gtest_pred_impl.h> // for Test, TestInfo, TEST, EXPEC...
+#include <memory>                  // for allocator, unique_ptr, __sh...
+#include <string>                  // for stoi, string
+
+namespace caosdb::connection {
+using caosdb::acm::User;
+
+TEST(test_user, test_create_single_user_failure_invalid_name) {
+  auto connection = ConnectionManager::GetDefaultConnection();
+  User user("CaosDB", "-user1");
+  EXPECT_THROW_STARTS_WITH(
+    connection->CreateSingleUser(user), caosdb::exceptions::Exception,
+    "The attempt to execute this transaction was not successful because an error occured in the "
+    "transport or RPC protocol layer. Original error: 2 - The user name does not comply with the "
+    "current policies for user names:");
+}
+
+TEST(test_user, test_create_single_user_failure_invalid_password) {
+  auto connection = ConnectionManager::GetDefaultConnection();
+  User user("CaosDB", "user1");
+  user.SetPassword("1234");
+  EXPECT_THROW_STARTS_WITH(
+    connection->CreateSingleUser(user), caosdb::exceptions::Exception,
+    "The attempt to execute this transaction was not successful because an error occured in the "
+    "transport or RPC protocol layer. Original error: 2 - The password does not comply with the "
+    "current policies for passwords: ");
+}
+
+TEST(test_user, test_create_single_user_success) {
+  auto connection = ConnectionManager::GetDefaultConnection();
+  User user("CaosDB", "user1");
+  user.SetPassword("Password1!");
+  connection->CreateSingleUser(user);
+  auto re = connection->RetrieveSingleUser("CaosDB", "user1");
+  EXPECT_EQ(re.GetName(), user.GetName());
+  connection->DeleteSingleUser("CaosDB", "user1");
+  EXPECT_THROW_MESSAGE(
+    connection->RetrieveSingleUser("CaosDB", "user1"), caosdb::exceptions::Exception,
+    "The attempt to execute this transaction was not successful because an error occured in the "
+    "transport or RPC protocol layer. Original error: 5 - This account does not exist.");
+}
+
+} // namespace caosdb::connection