feat: E2E test harness with testcontainers + wiremock#576
Merged
Conversation
Split the binary into a lib + bin so integration tests in tests/ can import the dispatcher. Add minimal DI seams (inject reqwest::Client and OpenAI base URL into GptParameters; accept &GptParameters in handlers instead of &mut) without rewriting error handling. Add tests/common/mod.rs with: - testcontainers-backed Postgres and Redis spawners - wiremock-backed Telegram Bot API (Bot::set_api_url points at it) - wiremock-backed OpenAI completions endpoint - helper that dispatches a single Update through the real handler tree Add three E2E tests covering rust-mention, chat-gpt and url-summary flows end-to-end. Add a separate `e2e` job to .github/workflows/build.yml so the slow Docker-backed suite doesn't block unit-test feedback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cargo does not expand globs in --test selectors, so `cargo test --test '*'` fails with "no test target named *". Use `cargo test --tests` to run unit and integration tests in one shot. Also assert in dispatch_one that the handler tree resolved to Break(Ok(())) so failures distinguish "no routing" from "routed but missed wiremock". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two runtime bugs surfaced once the suite ran against a real container
runtime (podman, exposing /var/run/docker.sock so testcontainers works
transparently):
1. teloxide-core 0.10's UpdateKind::Deserialize tries next_key::<&str>
first and falls back to next_key::<String>, but serde_json::from_value
produces owned String keys for which the &str attempt advances the
cursor before failing. The fallback then sees an empty map and the
variant degrades silently to UpdateKind::Error(Object {}). Workaround:
round-trip through a JSON string so the borrowed-str path succeeds.
2. teloxide builds outbound URLs as `/bot{token}/{MethodName}` with
capitalized method names (`/SendMessage`, `/SendSticker`,
`/RestrictChatMember`), not the lowercased forms used by the Telegram
Bot API docs. wiremock path matchers updated to match.
Verified locally: 8 unit + 3 E2E integration tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ntain permissions' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduce an end-to-end test harness for
rust-botso handler regressions are actually caught.src/lib.rsre-exports modules and the boot logic,src/main.rsshrinks to env-loading. Letstests/import the dispatcher.GptParametersnow carries areqwest::Client+ OpenAI base URL; handlers take&GptParametersinstead of&mut. No error-handling rewrite (separate follow-up per RECOMMENDATIONS.md §1).tests/common/mod.rs) — testcontainers-managed Postgres + Redis, wiremock-backed Telegram Bot API (Bot::set_api_urlpoints at it), wiremock-backed OpenAI completions. Helper that dispatches a singleUpdatethrough the real handler tree and asserts it was routed.e2ejob in.github/workflows/build.yml; existingbuildjob (unit tests only) keeps fast feedback.Why this shape
Direct
Updateinjection (via dispatching to thedptree::Handlerdirectly) instead of mocking the full Telegram HTTP API. Reasons: it exercises business logic without testing teloxide internals, doesn't require Telegram JSON-shape fixtures to match teloxide's serde across version bumps, and is faster.Test plan
buildjob:cargo build+cargo test --lib(8 existing unit tests) passese2ejob:cargo test --testspasses — runs unit + 3 E2E integration tests with Docker (testcontainers Postgres + Redis + wiremock)cargo fmt --check,cargo check --all-targetsclean (verified)rust_mention_e2efailsOut of scope (follow-up PRs)
Per
RECOMMENDATIONS.md(kept local, gitignored):🤖 Generated with Claude Code