mockall generates Rust mock traits from an attribute and enforces call expectations
A powerful mock object library for Rust
At a glance
- What is it?
- Mockall is a mocking library for Rust built on procedural macros: the automock attribute generates a Mock struct whose methods are recorded as expectations with predicates, call counts and return values. It is written in safe, stable Rust with an MSRV of 1.77.0.
- Who is it for?
- Adopt mockall when you unit-test Rust traits and want expectations checked at run time, since the with, times and returning combinators turn a wrong call into a test failure rather than a silent pass. Do not reach for it in integration tests where a real implementation is available.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- asomers/mockall1,849 ★ · +0
| Repository | 2026-10-16 | 2026-10-23 |
|---|---|---|
| asomers/mockall | 1.8k | 1.8k |
0 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Why static typing made this hard, and what the macros generate
A mock object presents the same interface as the real thing while every response is controlled by test code. The payoff is that a unit test can exercise the upper layers of an application without constructing the lower ones, and can inject error paths that the real stack would never produce.
The README is blunt about the difficulty: statically typed languages are harder to mock than dynamic ones, and earlier Rust attempts had mixed results. mockall's answer is procedural macros. The `automock` attribute on a trait generates a companion Mock struct whose methods take a builder-style chain rather than a body. What that macro emits is not documented in the README, so the safe assumption is that you get a struct named after the trait with a Mock prefix, methods that record expectations, and a new() constructor.
The library states it is written in 100% safe and stable Rust, meaning no nightly feature gates and no unsafe blocks. For a dev dependency that ends up in every test binary on a CI machine, that constraint is part of the value rather than a footnote.
Expectations are a chain of predicates, counts and return values
The usage example is short enough to read in full, and every line carries a decision. The test creates the mock, names the method it expects, narrows the accepted arguments with a predicate, constrains how many times it may be called, and supplies the response.
let mut mock = MockMyTrait::new();
mock.expect_foo()
.with(eq(4))
.times(1)
.returning(|x| x + 1);
assert_eq!(5, mock.foo(4));`with(eq(4))` restricts the argument to exactly 4, drawn from `predicate::*`. `times(1)` states the expected call count. `returning` maps the call into a value. Because the mock is declared `mut`, the expectation is set up on a mutable binding before the call.
The assertion at the end checks the returned value, not the call. That is the pattern to be aware of: if you assert only on the result, a mock whose expectations never fired still passes unless the times constraint is what fails the test. Setting expectations you never assert against is how a unit test drifts into asserting nothing.
Note also that the whole block is gated. `#[cfg(test)]` guards the import and the test module, and `#[cfg_attr(test, automock)]` applies the macro only when compiling tests, so the trait itself carries no test-only code in a normal build.
Installing it as a dev dependency, not a runtime one
mockall is meant to be used by unit tests, so it belongs in the dev-dependencies table. The README gives the version as 0.15.0.
[dev-dependencies]
mockall = "0.15.0"Dev-dependencies do not reach production builds, so the macros and the mock structs never enter the binary you ship. That is the practical reason to keep it out of `[dependencies]`, and it is worth checking in a codebase where a proc macro dependency has crept into the main dependency list.
The crate is published on crates.io and documented on docs.rs, both linked from the README badges. There are no GitHub releases for this repository; version information comes from the crate and the CHANGELOG.md at the repository root.
The repository is a Cargo workspace with three members: mockall, mockall_derive and mockall_double. The split explains the shape of the crate. mockall_derive holds the procedural macros, mockall is the runtime side users import, and mockall_double exists to provide double references, which the README does not document in detail.
The MSRV is a promise, not an accident
Mockall is supported on Rust 1.77.0 and higher, and the README states the MSRV will not change in the future without a major or minor version bump. That is a stronger commitment than most crates make, and it matters most for library authors: if you depend on mockall in your test suite and you support old toolchains, this is the guarantee that lets you avoid pinning.
The workspace carries a file named Cargo.lock.msrv, which is the mechanism for checking that claim in CI rather than asserting it in prose. There is a clippy.toml and a CI workflow as well.
For a team on a nightly toolchain, the flip side is that mockall will not adopt nightly-only features to gain capability, because that would break the guarantee. If you need something that requires unstable features, this is not the crate.
Licensing is dual: the README states mockall is primarily distributed under both the MIT license and the Apache License (Version 2.0), with LICENSE-APACHE and LICENSE-MIT in the repository root. Cargo metadata for the workspace records Apache-2.0. Either way, it is a permissive licence for a dev dependency, subject to its notice and licence conditions.
Where mockall is the wrong tool
The main failure mode is over-mocking. When the upper layer is tested against a mock of every collaborator, the test asserts the shape of the mock chain rather than the behaviour of the code under test, and the suite passes while production breaks. mockall does not guard against that; the ergonomics of the expectation chain actively make more mocks easy to write.
There is also a compile-time cost. Every trait you annotate with automock generates code, and generated mocks for a wide surface compile once per test binary. For a large trait graph this shows up as slower test builds rather than slower tests.
The alternative approach is a hand-written stub: a plain struct implementing the trait, with fields or closures for the responses. It needs no macro, adds no dependency, and costs more typing for anything beyond two methods. The difference in approach is between a checked, generated expectation system and an unchecked value you read back in assertions. If you want the check, take the macro; if you want a test that compiles fast and has no extra dependency, the hand-written stub is often the smaller total cost.
A third option, a trait with a default method or a real in-memory implementation, removes the mock entirely. That is the better design whenever the real implementation is cheap to construct.
Editorial conclusion
Adopt mockall when you unit-test Rust traits and want expectations checked at run time, since the with, times and returning combinators turn a wrong call into a test failure rather than a silent pass. Do not reach for it in integration tests where a real implementation is available. Before pinning 0.15.0, check that your toolchain meets the stated MSRV of 1.77.0.
Frequently asked questions
How do I add mockall to a Rust project?
Add mockall = "0.15.0" to the [dev-dependencies] table in Cargo.toml, import automock, mock and predicate::* behind #[cfg(test)], and annotate the trait with #[cfg_attr(test, automock)]. The generated Mock struct is then available in your test module.
What Rust version does mockall require?
Mockall is supported on Rust 1.77.0 and higher. The README states the MSRV will not be raised without a major or minor version bump, and the repository carries a Cargo.lock.msrv file for checking that.
What does the with, times and returning chain do in mockall?
They build the expectation for a mocked method. with(eq(4)) restricts the accepted arguments using a predicate from predicate::*, times(1) constrains how many times the method may be called, and returning supplies the value or closure that produces the response.
What license is mockall distributed under?
The README states mockall is primarily distributed under both the MIT license and the Apache License (Version 2.0), with LICENSE-APACHE and LICENSE-MIT in the repository root. The README names both Apache-2.0 and MIT.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/asomers-mockall)Star history chart for your README
[](https://hysenlabs.com/projects/asomers-mockall)Was this useful?