The ecewo-mock.h file provides a lightweight HTTP mocking plugin for Ecewo applications. It allows you to test your routes, handlers, and middleware without starting an actual HTTP server.
Note
This plugin is for mocking HTTP request only. It doesn't provide assert macros. The assert macros used in this documentation were taken from the savashn/myassert repository.
Add to your CMakeLists.txt:
ecewo_plugin(mock)
target_link_libraries(app PRIVATE
ecewo::ecewo
ecewo::mock
)HTTP methods supported by the mock framework:
typedef enum
{
GET,
POST,
PUT,
DELETE,
PATCH,
OPTIONS
} MockMethod;Represents an HTTP header key-value pair:
typedef struct {
const char *key;
const char *value;
} MockHeaders;Parameters for creating a mock HTTP request:
typedef struct
{
MockMethod method; // HTTP method
const char *path; // Request path (e.g., "/users/123")
const char *body; // Request body (optional, can be NULL)
MockHeaders *headers; // Array of headers (optional)
size_t header_count; // Number of headers
} MockParams;Response returned by the mock plugin:
typedef struct
{
uint16_t status_code; // HTTP status code (e.g., 200, 404)
char *body; // Response body
size_t body_len; // Length of response body
} MockResponse;Execute a mock HTTP request:
MockResponse request(MockParams *params);Parameters:
params: Pointer to request parameters.
Returns:
MockResponse containing status code and response body.
Example:
MockParams params = {
.method = GET,
.path = "/users/123"
};
MockResponse res = request(¶ms);
ASSERT_EQ(200, res.status_code);
free_request(&res);Free memory allocated by a mock response:
void free_request(MockResponse *res);Parameters:
res: Pointer to response to free.
Example:
MockResponse res = request(¶ms);
// ... use response ...
free_request(&res); // Always call this!Initialize the mock testing environment:
int mock_init(test_routes_cb_t routes_callback);Parameters:
routes_callback: A callback that registers the routes.
Returns:
0 on success, non-zero on error
Clean up the mock testing environment:
void mock_cleanup(void);Get header of a response that received from the mocking request
const char *mock_get_header(MockResponse *res, const char *key);#include "ecewo.h"
#include "ecewo-mock.h"
#include "myassert.h"
void handler_new_user(Req *req, Res *res)
{
const char *authorization = get_header(req, "Authorization");
const char *content_type = get_header(req, "Content-Type");
const char *x_custom_header = get_header(req, "X-Custom-Header");
if (!authorization || !content_type || !x_custom_header)
{
send_text(res, BAD_REQUEST, "Missing required headers");
return;
}
if (!req->body || req->body_len == 0)
{
send_text(res, BAD_REQUEST, "Empty body");
return;
}
const char *expected_body = "{\"name\":\"John\",\"age\":30}";
if (strcmp(req->body, expected_body) != 0)
{
char *error = arena_sprintf(req->arena,
"Body mismatch. Expected: %s, Got: %s",
expected_body, req->body);
send_text(res, BAD_REQUEST, error);
return;
}
send_text(res, CREATED, "Success!");
}
int test_new_user(void)
{
MockHeaders headers[] = {
{"Authorization", "Bearer secret-token"},
{"Content-Type", "application/json"},
{"X-Custom-Header", "custom-value"}
};
const char *json_body = "{\"name\":\"John\",\"age\":30}";
MockParams params = {
.method = MOCK_POST,
.path = "/new/user",
.body = json_body,
.headers = headers,
.header_count = 3
};
MockResponse res = request(¶ms);
ASSERT_EQ(201, res.status_code);
ASSERT_EQ_STR("Success!", res.body);
free_request(&res);
RETURN_OK();
}
void setup_routes(void)
{
get("/new/user", handler_new_user);
}
int main(void)
{
mock_init(setup_routes);
RUN_TEST(test_new_user);
mock_cleanup();
return 0;
}void handler_with_response_headers(Req *req, Res *res)
{
set_header(res, "X-Request-ID", "12345");
set_header(res, "X-Rate-Limit", "100");
set_header(res, "Cache-Control", "no-cache");
send_text(res, 200, "OK");
}
int test_response_headers(void)
{
MockParams params = {
.method = MOCK_GET,
.path = "/test"
};
MockResponse res = request(¶ms);
ASSERT_EQ(200, res.status_code);
ASSERT_EQ_STR("12345", mock_get_header(&res, "X-Request-ID"));
ASSERT_EQ_STR("100", mock_get_header(&res, "X-Rate-Limit"));
ASSERT_EQ_STR("no-cache", mock_get_header(&res, "Cache-Control"));
free_request(&res);
RETURN_OK();
}