diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 89e0a8f7..ce2a2089 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -31,12 +31,27 @@ jobs:
           --health-retries 5
         ports:
           - 5432:5432
+      mssql:
+        image: mcr.microsoft.com/mssql/server:2019-latest
+        env:
+          SA_PASSWORD: P@ssw0rd
+          ACCEPT_EULA: 'Y'
+        ports:
+          - 1433:1433
+        options: >-
+          --health-cmd "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'P@ssw0rd' -d master -Q 'SELECT COUNT(*) FROM master.dbo.spt_values;'"
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
 
     strategy:
       matrix:
         php: [8.0, 8.1, 8.2]
 
     steps:
+    - name: Create default database for sqlsrv as image does not support it
+      run: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'P@ssw0rd' -Q 'CREATE DATABASE codeception_test'
+
     - name: Checkout code
       uses: actions/checkout@v2
 
@@ -44,7 +59,7 @@ jobs:
       uses: shivammathur/setup-php@v2
       with:
         php-version: ${{ matrix.php }}
-        extensions: pdo, pgsql, mysql, sqlite
+        extensions: pdo, pgsql, mysql, sqlite, sqlsrv, pdo_sqlsrv, pdo_dblib
         coverage: none
 
     - name: Validate composer.json and composer.lock
@@ -56,5 +71,11 @@ jobs:
     - name: Run test suite
       run: php vendor/bin/codecept run
       env:
-        PGPASSWORD: postgres
         MYSQL_HOST: 127.0.0.1
+        MYSQL_DB: codeception_test
+        PG_HOST: 127.0.0.1
+        PG_DB: codeception_test
+        PG_PASSWORD: postgres
+        MSSQL_HOST: 127.0.0.1
+        MSSQL_DB: codeception_test
+        MSSQL_PASSWORD: P@ssw0rd
diff --git a/docker-compose.yml b/docker-compose.yml
index b164309f..21e6d5dc 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,20 +7,46 @@ services:
       context: .
       dockerfile: ./php81.Dockerfile
     environment:
-      MYSQL_DSN: "mysql:host=host.docker.internal;port=3102;dbname=codeception"
-      MYSQL_USER: root
+      MYSQL_HOST: host.docker.internal
+      MYSQL_DB: codeception
       MYSQL_PASSWORD: codeception
+      PG_HOST: host.docker.internal
+      PG_DB: codeception
+      PG_PASSWORD: codeception
+      MSSQL_HOST: host.docker.internal
+      MSSQL_DB: codeception
+      MSSQL_PASSWORD: 'P@ssw0rd'
       XDEBUG_MODE: "debug"
       XDEBUG_CONFIG: "client_host=host.docker.internal; client_port=9000; mode=debug; start_wih_request=1"
       PHP_IDE_CONFIG: "serverName=codeception-module-db" # the name must be the same as in your PHP -> Server -> "name" field
     volumes:
       - ".:/var/www/html"
 
-  mariadb105:
-    image: mariadb:10.5
+  mysql:
+    image: mysql:5.7
     environment:
-      MARIADB_ROOT_PASSWORD: codeception
-      MARIADB_DATABASE: codeception
+      MYSQL_ROOT_PASSWORD: codeception
+      MYSQL_DATABASE: codeception
     ports:
-      - "3102:3306"
+      - "3306:3306"
+
+  postgres:
+    image: postgres
+    environment:
+      POSTGRES_PASSWORD: codeception
+      POSTGRES_DB: codeception
+    ports:
+      - "5432:5432"
+
+  mssql:
+    image: mcr.microsoft.com/mssql/server:2019-latest
+    environment:
+      SA_PASSWORD: 'P@ssw0rd'
+      MSSQL_DATABASE: codeception
+      ACCEPT_EULA: 'Y'
+    ports:
+      - "1433:1433"
+    volumes:
+      - ./tests/data/scripts:/scripts:ro
+    entrypoint: [ "/bin/bash", "-c", "/scripts/mssql.sh" ]
 
diff --git a/php81.Dockerfile b/php81.Dockerfile
index 9e6b8bcd..ca24ccde 100644
--- a/php81.Dockerfile
+++ b/php81.Dockerfile
@@ -1,5 +1,7 @@
 FROM php:8.1-cli
 
+COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
+
 RUN apt-get update && \
     apt-get install -y \
         unzip \
@@ -7,27 +9,21 @@ RUN apt-get update && \
         git \
         zlib1g-dev \
         libzip-dev \
-		mariadb-client-10.5
-
-RUN docker-php-ext-install pdo pdo_mysql && docker-php-ext-enable pdo pdo_mysql
-RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
-RUN docker-php-ext-install zip
-
-RUN pecl install xdebug-3.1.5 && \
-    echo zend_extension=xdebug.so > $PHP_INI_DIR/conf.d/xdebug.ini
+        libpq-dev \
+        mariadb-client-10.5
+
+RUN install-php-extensions \
+    pdo_mysql-stable \
+    pdo_pgsql-stable \
+    pdo_dblib-stable \
+    pdo_sqlsrv-5.11.0 \
+    pgsql-stable \
+    zip-stable \
+    xdebug-3.1.5
 
 COPY --from=composer /usr/bin/composer /usr/bin/composer
 
 WORKDIR /var/www/html
 
-COPY composer.json .
-COPY composer.lock .
-
-RUN composer install --no-autoloader
-
-COPY . .
-
-RUN composer dump-autoload -o
-
 ENTRYPOINT ["tail"]
 CMD ["-f", "/dev/null"]
diff --git a/src/Codeception/Lib/Driver/Db.php b/src/Codeception/Lib/Driver/Db.php
index b5680459..2f7385ec 100755
--- a/src/Codeception/Lib/Driver/Db.php
+++ b/src/Codeception/Lib/Driver/Db.php
@@ -250,7 +250,7 @@ public function deleteQueryByCriteria(string $tableName, array $criteria): void
 
     public function lastInsertId(string $tableName): string
     {
-        return $this->getDbh()->lastInsertId();
+        return (string)$this->getDbh()->lastInsertId();
     }
 
     public function getQuotedName(string $name): string
diff --git a/tests/data/dumps/mssql.sql b/tests/data/dumps/mssql.sql
new file mode 100644
index 00000000..93fe7075
--- /dev/null
+++ b/tests/data/dumps/mssql.sql
@@ -0,0 +1,76 @@
+CREATE TABLE [dbo].[groups] (
+    [id] INT NOT NULL IDENTITY(1,1),
+    [name] VARCHAR(100) NULL,
+    [enabled] BIT NULL,
+    [created_at] DATETIME NOT NULL CONSTRAINT DF_groups_created_at DEFAULT GETDATE(),
+    CONSTRAINT PK_groups PRIMARY KEY CLUSTERED ([id] ASC)
+);
+
+INSERT INTO [dbo].[groups]([name],[enabled],[created_at])
+VALUES
+    ('coders', 1, '2012-02-01 21:17:50'),
+    ('jazzman', 0, '2012-02-01 21:18:40');
+
+
+CREATE TABLE [dbo].[users] (
+    [id] INT NOT NULL IDENTITY(1,1),
+    [uuid] BINARY(16) NULL,
+    [name] VARCHAR(30) NULL,
+    [email] VARCHAR(255) NULL,
+    [is_active] BIT NOT NULL CONSTRAINT DF_users_is_active DEFAULT 1,
+    [created_at] DATETIME NOT NULL CONSTRAINT DF_users_created_at DEFAULT GETDATE(),
+    CONSTRAINT PK_users PRIMARY KEY CLUSTERED ([id] ASC)
+);
+
+INSERT INTO [dbo].[users]([uuid],[name],[email],[is_active],[created_at])
+VALUES
+    (0x11edc34b01d972fa9c1d0242ac120006, 'davert', 'davert@mail.ua', 1, '2012-02-01 21:17:04'),
+    (null, 'nick', 'nick@mail.ua', 1, '2012-02-01 21:17:15'),
+    (null, 'miles', 'miles@davis.com', 1, '2012-02-01 21:17:25'),
+    (null, 'bird', 'charlie@parker.com', 0, '2012-02-01 21:17:39');
+
+
+CREATE TABLE [dbo].[permissions] (
+    [id] INT NOT NULL IDENTITY(1,1),
+    [user_id] INT NULL,
+    [group_id] INT NULL,
+    [role] VARCHAR(30) NULL,
+    CONSTRAINT PK_permissions PRIMARY KEY CLUSTERED ([id] ASC),
+    CONSTRAINT FK_permissions FOREIGN KEY ([group_id]) REFERENCES [dbo].[groups] ([id]) ON DELETE CASCADE,
+    CONSTRAINT FK_users FOREIGN KEY ([user_id]) REFERENCES [dbo].[users] ([id]) ON DELETE CASCADE
+);
+
+INSERT INTO [dbo].[permissions]([user_id],[group_id],[role])
+VALUES
+    (1,1,'member'),
+    (2,1,'member'),
+    (3,2,'member'),
+    (4,2,'admin');
+
+
+CREATE TABLE [dbo].[order] (
+    [id] INT NOT NULL IDENTITY(1,1),
+    [name] VARCHAR(255) NOT NULL,
+    [status] VARCHAR(255) NOT NULL,
+    CONSTRAINT PK_order PRIMARY KEY CLUSTERED ([id] ASC)
+);
+
+INSERT INTO [dbo].[order]([name],[status]) VALUES ('main', 'open');
+
+
+CREATE TABLE [dbo].[composite_pk] (
+    [group_id] INT NOT NULL,
+    [id] INT NOT NULL,
+    [status] VARCHAR(255) NOT NULL,
+    CONSTRAINT PK_composite_pk PRIMARY KEY CLUSTERED ([group_id] ASC, [id] ASC)
+);
+
+CREATE TABLE [dbo].[no_pk] (
+    [status] varchar(255) NOT NULL
+);
+
+CREATE TABLE [dbo].[empty_table] (
+    [id] int NOT NULL IDENTITY(1,1),
+    [field] varchar(255),
+    CONSTRAINT [PK_empty_table] PRIMARY KEY CLUSTERED ([id])
+);
diff --git a/tests/data/scripts/mssql.sh b/tests/data/scripts/mssql.sh
new file mode 100755
index 00000000..84434578
--- /dev/null
+++ b/tests/data/scripts/mssql.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+/opt/mssql/bin/sqlservr &
+/scripts/wait-for-it.sh 127.0.0.1:1433
+
+for i in {1..50};
+do
+    /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -d master -Q "CREATE DATABASE $MSSQL_DATABASE;"
+    if [ $? -eq 0 ]
+    then
+        echo "database created"
+        break
+    else
+        echo "not ready yet..."
+        sleep 1
+    fi
+done
+
+sleep infinity # Keep the container running forever
diff --git a/tests/data/scripts/wait-for-it.sh b/tests/data/scripts/wait-for-it.sh
new file mode 100644
index 00000000..44768829
--- /dev/null
+++ b/tests/data/scripts/wait-for-it.sh
@@ -0,0 +1,184 @@
+#!/usr/bin/env bash
+# Use this script to test if a given TCP host/port are available
+
+#Source: https://github.com/vishnubob/wait-for-it/blob/81b1373f17855a4dc21156cfe1694c31d7d1792e/wait-for-it.sh
+
+WAITFORIT_cmdname=${0##*/}
+
+echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
+
+usage()
+{
+    cat << USAGE >&2
+Usage:
+    $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
+    -h HOST | --host=HOST       Host or IP under test
+    -p PORT | --port=PORT       TCP port under test
+                                Alternatively, you specify the host and port as host:port
+    -s | --strict               Only execute subcommand if the test succeeds
+    -q | --quiet                Don't output any status messages
+    -t TIMEOUT | --timeout=TIMEOUT
+                                Timeout in seconds, zero for no timeout
+    -- COMMAND ARGS             Execute command with args after the test finishes
+USAGE
+    exit 1
+}
+
+wait_for()
+{
+    if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
+        echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
+    else
+        echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
+    fi
+    WAITFORIT_start_ts=$(date +%s)
+    while :
+    do
+        if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
+            nc -z $WAITFORIT_HOST $WAITFORIT_PORT
+            WAITFORIT_result=$?
+        else
+            (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
+            WAITFORIT_result=$?
+        fi
+        if [[ $WAITFORIT_result -eq 0 ]]; then
+            WAITFORIT_end_ts=$(date +%s)
+            echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
+            break
+        fi
+        sleep 1
+    done
+    return $WAITFORIT_result
+}
+
+wait_for_wrapper()
+{
+    # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
+    if [[ $WAITFORIT_QUIET -eq 1 ]]; then
+        timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
+    else
+        timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
+    fi
+    WAITFORIT_PID=$!
+    trap "kill -INT -$WAITFORIT_PID" INT
+    wait $WAITFORIT_PID
+    WAITFORIT_RESULT=$?
+    if [[ $WAITFORIT_RESULT -ne 0 ]]; then
+        echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
+    fi
+    return $WAITFORIT_RESULT
+}
+
+# process arguments
+while [[ $# -gt 0 ]]
+do
+    case "$1" in
+        *:* )
+        WAITFORIT_hostport=(${1//:/ })
+        WAITFORIT_HOST=${WAITFORIT_hostport[0]}
+        WAITFORIT_PORT=${WAITFORIT_hostport[1]}
+        shift 1
+        ;;
+        --child)
+        WAITFORIT_CHILD=1
+        shift 1
+        ;;
+        -q | --quiet)
+        WAITFORIT_QUIET=1
+        shift 1
+        ;;
+        -s | --strict)
+        WAITFORIT_STRICT=1
+        shift 1
+        ;;
+        -h)
+        WAITFORIT_HOST="$2"
+        if [[ $WAITFORIT_HOST == "" ]]; then break; fi
+        shift 2
+        ;;
+        --host=*)
+        WAITFORIT_HOST="${1#*=}"
+        shift 1
+        ;;
+        -p)
+        WAITFORIT_PORT="$2"
+        if [[ $WAITFORIT_PORT == "" ]]; then break; fi
+        shift 2
+        ;;
+        --port=*)
+        WAITFORIT_PORT="${1#*=}"
+        shift 1
+        ;;
+        -t)
+        WAITFORIT_TIMEOUT="$2"
+        if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
+        shift 2
+        ;;
+        --timeout=*)
+        WAITFORIT_TIMEOUT="${1#*=}"
+        shift 1
+        ;;
+        --)
+        shift
+        WAITFORIT_CLI=("$@")
+        break
+        ;;
+        --help)
+        usage
+        ;;
+        *)
+        echoerr "Unknown argument: $1"
+        usage
+        ;;
+    esac
+done
+
+if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
+    echoerr "Error: you need to provide a host and port to test."
+    usage
+fi
+
+WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
+WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
+WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
+WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
+
+# Check to see if timeout is from busybox?
+WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
+WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
+
+WAITFORIT_BUSYTIMEFLAG=""
+if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
+    WAITFORIT_ISBUSY=1
+    # Check if busybox timeout uses -t flag
+    # (recent Alpine versions don't support -t anymore)
+    if timeout &>/dev/stdout | grep -q -e '-t '; then
+        WAITFORIT_BUSYTIMEFLAG="-t"
+    fi
+else
+    WAITFORIT_ISBUSY=0
+fi
+
+if [[ $WAITFORIT_CHILD -gt 0 ]]; then
+    wait_for
+    WAITFORIT_RESULT=$?
+    exit $WAITFORIT_RESULT
+else
+    if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
+        wait_for_wrapper
+        WAITFORIT_RESULT=$?
+    else
+        wait_for
+        WAITFORIT_RESULT=$?
+    fi
+fi
+
+if [[ $WAITFORIT_CLI != "" ]]; then
+    if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
+        echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
+        exit $WAITFORIT_RESULT
+    fi
+    exec "${WAITFORIT_CLI[@]}"
+else
+    exit $WAITFORIT_RESULT
+fi
diff --git a/tests/unit/Codeception/Lib/Driver/MysqlTest.php b/tests/unit/Codeception/Lib/Driver/MysqlTest.php
index eda908ae..94ea59f6 100644
--- a/tests/unit/Codeception/Lib/Driver/MysqlTest.php
+++ b/tests/unit/Codeception/Lib/Driver/MysqlTest.php
@@ -25,9 +25,15 @@ final class MysqlTest extends Unit
 
     public static function _setUpBeforeClass()
     {
-        $host = getenv('MYSQL_HOST') ? getenv('MYSQL_HOST') : 'localhost';
-        self::$config['dsn'] = 'mysql:host='.$host.';dbname=codeception_test';
-        self::$config['password'] = getenv('MYSQL_PASSWORD') ? getenv('MYSQL_PASSWORD') : '';
+        $host = getenv('MYSQL_HOST') ?: 'localhost';
+        $user = getenv('MYSQL_USER') ?: 'root';
+        $password = getenv('MYSQL_PASSWORD') ?: '';
+        $database = getenv('MYSQL_DB') ?: 'codeception_test';
+        $dsn = getenv('MYSQL_DSN') ?: 'mysql:host=' . $host . ';dbname=' . $database;
+
+        self::$config['dsn'] = $dsn;
+        self::$config['user'] = $user;
+        self::$config['password'] = $password;
 
         $sql = file_get_contents(\Codeception\Configuration::dataDir() . '/dumps/mysql.sql');
         $sql = preg_replace('#/\*(?:(?!\*/).)*\*/#s', "", $sql);
diff --git a/tests/unit/Codeception/Lib/Driver/PostgresTest.php b/tests/unit/Codeception/Lib/Driver/PostgresTest.php
index 7e66826f..b0982021 100644
--- a/tests/unit/Codeception/Lib/Driver/PostgresTest.php
+++ b/tests/unit/Codeception/Lib/Driver/PostgresTest.php
@@ -27,10 +27,26 @@ public static function _setUpBeforeClass()
         if (!function_exists('pg_connect')) {
             return;
         }
-        self::$config['password'] = getenv('PGPASSWORD') ? getenv('PGPASSWORD') : null;
-        $sql = file_get_contents(codecept_data_dir('dumps/postgres.sql'));
+
+        $host = getenv('PG_HOST') ?: 'localhost';
+        $user = getenv('PG_USER') ?: 'postgres';
+        $password = getenv('PG_PASSWORD') ?: null;
+        $database = getenv('PG_DB') ?: 'codeception_test';
+        $dsn = getenv('PG_DSN') ?: 'pgsql:host=' . $host . ';dbname=' . $database;
+
+        self::$config['dsn'] = $dsn;
+        self::$config['user'] = $user;
+        self::$config['password'] = $password;
+
+        $sql = file_get_contents(\Codeception\Configuration::dataDir() . '/dumps/postgres.sql');
         $sql = preg_replace('#/\*(?:(?!\*/).)*\*/#s', '', $sql);
         self::$sql = explode("\n", $sql);
+
+        try {
+            $postgres = Db::create(self::$config['dsn'], self::$config['user'], self::$config['password']);
+            $postgres->cleanup();
+        } catch (Exception $e) {
+        }
     }
 
     public function _setUp()
diff --git a/tests/unit/Codeception/Module/Db/AbstractDbTest.php b/tests/unit/Codeception/Module/Db/AbstractDbTest.php
index f880866b..81ad0942 100644
--- a/tests/unit/Codeception/Module/Db/AbstractDbTest.php
+++ b/tests/unit/Codeception/Module/Db/AbstractDbTest.php
@@ -66,6 +66,13 @@ public function testConnectionIsKeptForTheWholeSuite()
 
     public function testSeeInDatabaseWithBinary()
     {
+        if (
+            $this instanceof MssqlSqlSrvDbTest
+            || $this instanceof MssqlDblibDbTest
+        ) {
+            $this->markTestSkipped('Filter to binary field does not supported by SqlSrv driver');
+        }
+
         $this->module->seeInDatabase('users', ['uuid' => hex2bin('11edc34b01d972fa9c1d0242ac120006')]);
     }
 
@@ -76,18 +83,40 @@ public function testSeeInDatabase()
 
     public function testCountInDatabase()
     {
-        $this->module->seeNumRecords(1, 'users', ['uuid' => hex2bin('11edc34b01d972fa9c1d0242ac120006')]);
         $this->module->seeNumRecords(1, 'users', ['name' => 'davert']);
         $this->module->seeNumRecords(0, 'users', ['name' => 'davert', 'email' => 'xxx@yyy.zz']);
         $this->module->seeNumRecords(0, 'users', ['name' => 'user1']);
     }
 
+    public function testCountInDatabaseWithBinary()
+    {
+        if (
+            $this instanceof MssqlSqlSrvDbTest
+            || $this instanceof MssqlDblibDbTest
+        ) {
+            $this->markTestSkipped('Filter to binary field does not supported by SqlSrv driver');
+        }
+
+        $this->module->seeNumRecords(1, 'users', ['uuid' => hex2bin('11edc34b01d972fa9c1d0242ac120006')]);
+    }
+
     public function testDontSeeInDatabase()
     {
-        $this->module->dontSeeInDatabase('users', ['uuid' => hex2bin('ffffffffffffffffffffffffffffffff')]);
         $this->module->dontSeeInDatabase('users', ['name' => 'user1']);
     }
 
+    public function testDontSeeInDatabaseWithBinary()
+    {
+        if (
+            $this instanceof MssqlSqlSrvDbTest
+            || $this instanceof MssqlDblibDbTest
+        ) {
+            $this->markTestSkipped('Filter to binary field does not supported by SqlSrv driver');
+        }
+
+        $this->module->dontSeeInDatabase('users', ['uuid' => hex2bin('ffffffffffffffffffffffffffffffff')]);
+    }
+
     public function testDontSeeInDatabaseWithEmptyTable()
     {
         $this->module->dontSeeInDatabase('empty_table');
diff --git a/tests/unit/Codeception/Module/Db/MssqlDblibDbTest.php b/tests/unit/Codeception/Module/Db/MssqlDblibDbTest.php
new file mode 100644
index 00000000..e9b46fff
--- /dev/null
+++ b/tests/unit/Codeception/Module/Db/MssqlDblibDbTest.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+use Codeception\Configuration;
+
+require_once Configuration::testsDir() . 'unit/Codeception/Module/Db/AbstractDbTest.php';
+
+/**
+ * @group db
+ */
+final class MssqlDblibDbTest extends AbstractDbTest
+{
+    public function getPopulator(): string
+    {
+        $config = $this->getConfig();
+
+        return sprintf('/opt/mssql-tools/bin/sqlcmd -S $host -U $user -P $password -d $dbname -i %s', $config['dump']);
+    }
+
+    public function getConfig(): array
+    {
+        $host = getenv('MSSQL_HOST') ?: 'localhost';
+        $user = getenv('MSSQL_USER') ?: 'sa';
+        $password = getenv('MSSQL_PASSWORD') ?: '';
+        $database = getenv('MSSQL_DB') ?: 'codeception_test';
+        $dsn = getenv('MSSQL_DSN') ?: 'dblib:host=' . $host . ';dbname=' . $database;
+
+        return [
+            'dsn' => $dsn,
+            'user' => $user,
+            'password' => $password,
+            'dump' => 'tests/data/dumps/mssql.sql',
+            'reconnect' => true,
+            'cleanup' => true,
+            'populate' => true,
+        ];
+    }
+}
diff --git a/tests/unit/Codeception/Module/Db/MssqlSqlSrvDbTest.php b/tests/unit/Codeception/Module/Db/MssqlSqlSrvDbTest.php
new file mode 100644
index 00000000..58776042
--- /dev/null
+++ b/tests/unit/Codeception/Module/Db/MssqlSqlSrvDbTest.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+use Codeception\Configuration;
+
+require_once Configuration::testsDir() . 'unit/Codeception/Module/Db/AbstractDbTest.php';
+
+/**
+ * @group db
+ */
+final class MssqlSqlSrvDbTest extends AbstractDbTest
+{
+    public function getPopulator(): string
+    {
+        $config = $this->getConfig();
+
+        return sprintf('/opt/mssql-tools/bin/sqlcmd -S $Server -U $user -P $password -d $Database -i %s', $config['dump']);
+    }
+
+    public function getConfig(): array
+    {
+        $host = getenv('MSSQL_HOST') ?: 'localhost';
+        $user = getenv('MSSQL_USER') ?: 'sa';
+        $password = getenv('MSSQL_PASSWORD') ?: '';
+        $database = getenv('MSSQL_DB') ?: 'codeception_test';
+        $dsn = getenv('MSSQL_DSN') ?: 'sqlsrv:Server=' . $host . ';Database=' . $database;
+
+        return [
+            'dsn' => $dsn,
+            'user' => $user,
+            'password' => $password,
+            'dump' => 'tests/data/dumps/mssql.sql',
+            'reconnect' => true,
+            'cleanup' => true,
+            'populate' => true,
+        ];
+    }
+}
diff --git a/tests/unit/Codeception/Module/Db/MySqlDbTest.php b/tests/unit/Codeception/Module/Db/MySqlDbTest.php
index 058aa4f5..11dcfee0 100644
--- a/tests/unit/Codeception/Module/Db/MySqlDbTest.php
+++ b/tests/unit/Codeception/Module/Db/MySqlDbTest.php
@@ -22,10 +22,11 @@ public function getPopulator(): string
 
     public function getConfig(): array
     {
-        $host = getenv('MYSQL_HOST') ? getenv('MYSQL_HOST') : 'localhost';
-        $user = getenv('MYSQL_USER') ? getenv('MYSQL_USER') : 'root';
-        $password = getenv('MYSQL_PASSWORD') ? getenv('MYSQL_PASSWORD') : '';
-        $dsn = getenv('MYSQL_DSN') ? getenv('MYSQL_DSN') : 'mysql:host='.$host.';dbname=codeception_test';
+        $host = getenv('MYSQL_HOST') ?: 'localhost';
+        $user = getenv('MYSQL_USER') ?: 'root';
+        $password = getenv('MYSQL_PASSWORD') ?: '';
+        $database = getenv('MYSQL_DB') ?: 'codeception_test';
+        $dsn = getenv('MYSQL_DSN') ?: 'mysql:host=' . $host . ';dbname=' . $database;
 
         return [
             'dsn' => $dsn,
diff --git a/tests/unit/Codeception/Module/Db/PostgreSqlDbTest.php b/tests/unit/Codeception/Module/Db/PostgreSqlDbTest.php
index fbdae270..9ebf1dd3 100644
--- a/tests/unit/Codeception/Module/Db/PostgreSqlDbTest.php
+++ b/tests/unit/Codeception/Module/Db/PostgreSqlDbTest.php
@@ -13,7 +13,9 @@ final class PostgreSqlDbTest extends AbstractDbTest
 {
     public function getPopulator(): string
     {
-        return "psql -h localhost -d codeception_test -U postgres  < tests/data/dumps/postgres.sql";
+        $config = $this->getConfig();
+
+        return sprintf('psql -h $host -d $dbname -U $user < %s', $config['dump']);
     }
 
     public function getConfig(): array
@@ -22,11 +24,15 @@ public function getConfig(): array
             $this->markTestSkipped();
         }
 
-        $password = getenv('PGPASSWORD') ? getenv('PGPASSWORD') : null;
+        $host = getenv('PG_HOST') ?: 'localhost';
+        $user = getenv('PG_USER') ?: 'postgres';
+        $password = getenv('PG_PASSWORD') ?: null;
+        $database = getenv('PG_DB') ?: 'codeception_test';
+        $dsn = getenv('PG_DSN') ?: 'pgsql:host=' . $host . ';dbname=' . $database;
 
         return [
-            'dsn' => 'pgsql:host=localhost;dbname=codeception_test',
-            'user' => 'postgres',
+            'dsn' => $dsn,
+            'user' => $user,
             'password' => $password,
             'dump' => 'tests/data/dumps/postgres.sql',
             'reconnect' => true,
