Mocking Unit Test with Catch2 regarding Pub/Sub client and message broker (nats-server) using protobuf cross-platform data format

I have wrote them and posted to my GitHub repos from the official Alpine docker image

testing_nats_msg_broker_pub_sub_client_with_protobuf_alpine/README.md at main ¡ chanvichekaouk/testing_nats_msg_broker_pub_sub_client_with_protobuf_alpine

🧪 Mock Publisher–Broker–Subscriber Unit Test (Catch2 v3 + Protobuf + Alpine) This project demonstrates a mock unit‑test workflow between:

a Publisher client

a NATS message broker

a Subscriber client

using a cross‑platform Protobuf data format, tested with the Catch2 v3 framework and built on the official Alpine Linux image.

The goal is to validate message flow, multi‑subscriber behavior, and protobuf serialization/deserialization in a lightweight, reproducible environment.

🛠️ Compiling Tests Manually (g++) You can compile the test suite directly from the terminal:

g++ -Iinclude tests/*.cpp -o test_runners \
    -I/usr/local/include -L/usr/local/lib \
    -lCatch2Main -lCatch2

Run all tests under a tag:

./test_runners "[tag]"

Run only a specific section under a tag:

./test_runners "[tag]" -c "section_name"

Example:

Run all sections under the tag:

./test_runners "[multi_sub_receive_msg]"

Run only a specific section:

./test_runners "[multi_sub_receive_msg]" -c "Client connects successfully"

Another example:

./test_runners "[multi_sub_receive_msg]" -c "Multiple subscribers receive the same published message"

Screenshots 

image

📦Using Protobuf Data Format

Example .proto schema:

syntax = "proto3";

message Telemetry {
    int32 id = 1;
    int32 temp = 2;
}

🐧 Alpine vs glibc: Why Linking Protobuf Is Harder on Alpine On most Linux distributions that use glibc, linking Protobuf with Abseil is simple. But Alpine uses musl, and Abseil depends on glibc‑specific internals such as futex.

Because musl does not provide these interfaces, Alpine maintainers must:

  • patch Abseil heavily
  • disable unsupported features
  • split Abseil into ~130 micro‑libraries

Starting with Protobuf 4.x, Abseil became a mandatory dependency, which makes linking more complex on Alpine.

On glibc‑based systems (Ubuntu, Debian, Fedora) You can link with just a few Abseil libraries:

-labsl -labsl_strings -labsl_log

On Alpine (musl) You must explicitly link the micro‑libraries required by your generated Protobuf code:

-lprotobuf -lprotobuf-lite
-labsl_base -labsl_strings
-labsl_raw_logging_internal
-labsl_log_internal_check_op
-labsl_log_internal_message
-labsl_log_internal_nullguard

Example:

g++ -Iinclude -Iproto \
proto/*.cc tests/*.cpp \
-o test_runners \
-lprotobuf -lprotobuf-lite \
-labsl_base -labsl_strings \
-labsl_raw_logging_internal \
-labsl_log_internal_check_op \
-labsl_log_internal_message \
-labsl_log_internal_nullguard \
-lCatch2Main -lCatch2
image

Getting Catch2 v3 to work in alpine docker image

I have tried it today and so far Catch2 v2 works either using package installer or through dropping its header file or compiling its library from its github source code.

But for Catch2 v3, it also works but to compile our binary, we have to either use library Catch2Main to autogenerate main or create our own main code because alpine with Catch2 v3 does not work with auto-generation of main using #define CATCH_CONFIG_MAIN flag

test_main.cpp (alpine with catch2 does not work with this kind of auto-generated main flag)

#define CATCH_CONFIG_MAIN
#include <catch2/catch_all.hpp>

main.cpp (works since we defined our own main)

#include <catch2/catch_session.hpp>

int main(int argc, char* argv[]) {
Catch::Session session;
return session.run(argc, argv);
}

Or also work with Library mode with Catch2main to auto generate main

✅ this works since we use Catch2Main library

g++ test_math.cpp -o test -I/usr/local/include -L/usr/local/lib -lCatch2Main -lCatch2 

❌ this does not work as I have verified that #define CATCH_CONFIG_MAIN flag is not working

g++ test_main.cpp test_math.cpp -o test -I/usr/local/include

✅this works since we wrote our own main

g++ main.cpp test_math.cpp -o test -I/usr/local/include -lCatch2