Skip to main content
PolyTests is an in-memory implementation of ITelegramBotClient designed for automated testing. Register it instead of the real TelegramBotClient and you get a fully offline, deterministic test double that delivers synthetic updates to the polling loop with long-poll semantics and records every outgoing request for assertions.

Class overview

PolyTests requires no constructor arguments — instantiate it directly and pass it to DI:

Injecting updates

EnqueueUpdate

Adds a single update to the internal queue. If the polling loop is waiting (blocking on a long-poll), the signal fires immediately and the update is delivered in the next GetUpdates batch.

EnqueueUpdates

Enqueues multiple updates in order. Each update signals the polling loop independently, so updates are never lost even if they arrive faster than the loop processes them.

Asserting outgoing requests

SentRequests returns an IReadOnlyList<object> snapshot of every request the framework sent through the client, in the order they were made:
The list contains the strongly-typed request objects from Telegram.Bot.Requests. Use LINQ to filter:

BotUser

The User returned by GetMe calls. Its type is Telegram.Bot.Types.User. The default value is:
Override it before the test runs when your handlers read the bot’s identity:

Supported requests

PolyTests answers the subset of Telegram API requests that PolyBot’s own infrastructure uses. Anything outside this list throws NotSupportedException.
If your handlers call API methods not in the supported list (e.g. SendPhoto, EditMessageText, PinChatMessage), the test will throw NotSupportedException. Either avoid those calls in the test path or create your own ITelegramBotClient mock that handles them.

Long-poll semantics

GetUpdatesRequest is handled with genuine long-poll behaviour:
  1. If the queue contains updates, they are dequeued immediately (up to request.Limit, defaulting to 100) and returned as a batch.
  2. If the queue is empty, the method waits asynchronously until either EnqueueUpdate signals an update or the CancellationToken is cancelled.
  3. When StopAsync cancels the token, GetUpdatesRequest throws OperationCanceledException, ending the polling loop cleanly.
This means you can start the hosted service, enqueue an update, and let the loop deliver it — no Task.Delay polling or manual timing in tests.

Using PolyTests with AddPolyBotHostedPolling

Register PolyTests as ITelegramBotClient before calling AddPolyBotHostedPolling. The hosted service picks up the test client from DI:

Using PolyTests with AddPolyBotWebhook

For webhook integration tests, resolve the hosted service to trigger StartAsync, which calls SetWebhook, then stop it to trigger DeleteWebhook:
PolyTests is also used internally by PolyBotClient.RunTest(). If you prefer the higher-level UpdateMocker API (with its Message, Command, Callback, and InlineQuery helpers), see Test Harness.