Blog

How to test a Slack bot

Mock the client, fake the HTTP API, use a test workspace or run a local replica: what each one catches, what it misses and which tools exist.

Published Nov 2, 2026 · Updated Nov 5, 2026 · Patrick Liu

There are four ways to test a Slack bot, and each catches a different kind of mistake. A mock of the Slack client tests your own code. A fake Slack API tests the requests your bot sends. A test workspace tests installation, permissions and how messages look in Slack. A local replica of Slack tests what the bot did to a channel: which thread it replied in and how many messages it posted.

Most bots need two of them: mocks for the logic, and one approach that keeps state. This page compares the four using each tool's own documentation, lists the tools with their last release dates, and ends with what a Slack bot test should check. We make one of the replicas, Ancha, and it is in the table with the others.

The four approaches compared

ApproachCatchesMissesSlack accountTools
Mock the Slack clientYour handler logic: the bot called chat.postMessage with the arguments you expectMessage order, threads and retries, unless you wrote them into the mockNoThe mocks in your test framework (Jest, Vitest, pytest). For Bolt apps: @slack-wrench/jest-bolt-receiver (last published 2020) and slack-bolt-testcase (0.0.2, March 2025)
Fake the Slack HTTP APIThe requests your real SDK sends: methods, URLs and payloadsAnything the library does not implement, and any answer you staged wronglyNoslack-mock (last published 2018) and slack-testing-library (2021)
Test workspace or Slack developer sandboxInstallation, OAuth scopes, how Slack renders Block Kit, real rate limitsRepeatable runs: messages stay in the channel between runs, and nobody replies unless a person or a second bot doesYesA second workspace or a Slack developer sandbox. promptfoo's Slack provider checks a bot's replies in one
Stateful local replicaWhat the bot did to the channel: the thread it replied in and how many messages it posted. Each run starts from a defined stateInstallation, OAuth scopes and how Slack renders messagesNolocal-slack (MIT), Slack Simulator (GPL-3.0), Sandiz (0.1.0, July 2026), Drizz's Slack twin, Ancha

Release dates are from npm and PyPI. Everything in the table was checked on November 2, 2026.

Which approach should I use?

Use mocks for the code that decides what to say. They run in milliseconds and need nothing else.

Use a test workspace once, to check that the app installs, that its scopes are enough and that messages look right. A Slack developer sandbox is made for this.

Use a replica for behavior that spans a conversation: replying in the right thread, answering once, answering the right question. A mock answers the way you wrote it, so it cannot show these mistakes.

How do I mock the Slack API in tests?

Both official Slack SDKs let you change the URL the client talks to, so the bot's real calls can go to a fake server and the bot code stays the same. In Node, pass slackApiUrl to WebClient. Slack's documentation says: "The slackApiUrl option allows you to replace this prefix with another." In Python, pass base_url. Both default to https://slack.com/api/.

const slack = new WebClient(process.env.SLACK_BOT_TOKEN, {
  slackApiUrl: process.env.SLACK_API_URL,
});
slack = WebClient(
    token=os.environ["SLACK_BOT_TOKEN"],
    base_url=os.environ.get("SLACK_API_URL", "https://slack.com/api/"),
)

With the variables unset, the bot talks to Slack. A test sets them to the fake server's URL and a fake token.

A fake that answers with what you staged cannot show that a reply went into the wrong thread. Assert on what the fake stored after the run, not only on the requests it received.

Can I test a Slack bot without a Slack workspace?

Yes, for everything except what only Slack does. Mocks, a fake API and a local replica need no Slack account. A real workspace is still the only way to check that the app installs, that its OAuth scopes are enough and how Block Kit looks in the Slack client.

For that check Slack provides developer sandboxes, which it describes as "an Enterprise org environment (a network of two or more Slack workspace instances)". Its documentation says they come "without an additional cost", allows up to two active sandboxes at any given time with at most eight users each, and sets a default lifespan of six months, or one month for basic sandboxes.

What should a Slack bot test check?

Four things are worth a test. The first two show up in what ended up in the channel. The last two are easiest to test by replaying the situation against your handler: send it the same event twice, and give it a 429.

  • The reply is in the right thread. thread_ts is the ts of the message you are answering, and Slack's documentation says to use the parent message's ts, not a reply's. The call succeeds for any message in the channel, so only the channel's contents show the mistake.
  • The bot picks the right message. Slack's documentation says of conversations.history: "The most recent messages in the time range are returned first." Code that takes the last item of the list takes the oldest message.
  • One event produces one reply. Slack expects a 2xx response within three seconds. Otherwise it retries three times, nearly immediately and then after 1 minute and after 5 minutes, and marks each retry with an x-slack-retry-num header. A bot that does slow work before it responds can reply once per delivery. Send your handler the same event twice and count the replies.
  • Rate limits are handled. Slack answers 429 Too Many Requests with a Retry-After header, and chat.postMessage generally allows one message per second per channel. A bot that posts in a loop has to wait and retry. Give a mocked client a 429 with Retry-After and check that the bot waits.

How do I test a Slack bot that uses an LLM?

A bot whose replies come from a model can pass once and fail the next time, so run each scenario several times and count. Check what the bot did to the channel: which thread it replied in, how many messages it posted and whether the reply contains what it should. Leave exact wording to a model-graded check or a person.

Ancha runs each scenario a set number of times, each time on a fresh copy of the seeded workspace, and reports a pass rate. This is its output for the thread mistake above, from a support bot that takes the last item of the history list. The check reads #support after the run:

$ ancha run -n 3
✗ support-reply  0/3 (0%)
    ✗ answered  failed in 3/3 trials
      trial 1: The check wanted ≥1 message in #support from @support-bot in reply to @laura: "Our CSV exports have been empty since this…" containing "issues/" but found 0 matching; @support-bot has 1 message(s) in #support, 0 in that thread.

In trial 1 every API call returned 200 or 201. The check fails because the reply is in the thread of a two-day-old question. The Test a Slack bot guide in the docs walks through the same kind of mistake with the bot's code, ancha explain and the fix.

Have a failed run to reproduce? Reconstruct a test environment from agent traces maps a fictional recording to a scene and compares the original bot with a one-line fix.

Try it locally

Ancha is a CLI that runs your agent against replicas of 38 tools, Slack among them, and checks what the agent did. The Slack replica implements 22 Web API methods for a bot token and delivers Events API events. It needs Node.js 24 and no Slack account.

$ npm install -g @ancha-labs/cli
$ ancha init
$ ancha run

The Slack page in the docs lists the methods and how to connect an SDK, and the quickstart runs a small agent against four tools.

Questions

Does Slack have an official way to test a bot?

Slack provides developer sandboxes, described above, for trying an installed app in a separate workspace. For code-level tests, the Bolt for Python repository has an open issue asking for built-in test support (#380, opened June 2021, last updated April 2026). Tests for Bolt apps use the approaches above.

Is a Slack developer sandbox free?

Slack's documentation says sandboxes come "without an additional cost" and that "All developers can provision basic sandboxes with no paid plan or payment method required."

How do I test Slack events and Socket Mode locally?

With a real app, events sent over HTTP need a public URL, which is why guides often use a tunnel such as ngrok. Socket Mode removes that need: it lets an app use the Events API "without exposing a public HTTP Request URL". A local fake or replica runs on the same machine as the bot, so neither mode needs a tunnel.

Can the same bot code run against Slack and a test server?

Yes, if the API URL and the token come from environment variables, as in the two snippets above. With the URL unset, the client talks to https://slack.com/api/.

Written by Patrick Liu.