A powerful mock object library for Rust

Mock objects are a powerful technique for unit testing software

Mockall

.

Overview

. A mock object is an object with the same interface as a real object, but whose responses are all manually controlled by test code. They can be used to test the upper and middle layers of an application without instantiating the lower ones, or to inject edge and error cases that would be difficult or impossible to create when using the full stack.

Statically typed languages are inherently more difficult to mock than dynamically typed languages. Since Rust is a statically typed language, previous attempts at creating a mock object library have had mixed results. Mockall incorporates the best elements of previous designs, resulting in it having a rich feature set with a terse and ergonomic interface. Mockall is written in 100% safe and stable Rust.

Usage

Typically mockall is only used by unit tests. To use it this way, add this to your Cargo.toml:

[dev-dependencies]
mockall = "0.10.2"

Then use it like this:

#[cfg(test)]
use mockall::{automock, mock, predicate::*};
#[cfg_attr(test, automock)]
trait MyTrait {
    fn foo(&self, x: u32) -> u32;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn mytest() {
        let mut mock = MockMyTrait::new();
        mock.expect_foo()
            .with(eq(4))
            .times(1)
            .returning(|x| x + 1);
        assert_eq!(5, mock.foo(4));
    }
}

See the API docs for more information.

Minimum Supported Rust Version (MSRV)

Mockall is supported on Rust 1.42.0 and higher. Mockall's MSRV will not be changed in the future without bumping the major or minor version.

License

mockall is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE, and LICENSE-MIT for details

Acknowledgements

Mockall was not built in a day. JMock was probably the first popular mock object library. Many ports and imitations have been made, including GoogleMock for C++. Mockers, inspired by GoogleMock, was the first attempt to bring the concept to Rust. The now-defunct Mock_derive was the first library to generate mock objects with procedural macros, greatly reducing the user's workload. Mockall also uses proc macros, and copies many of Mockers' features and conventions. Mockall also takes inspiration from Simulacrum's internal design, and its technique for mocking generic methods.

Issues

Collection of the latest Issues

glueball

glueball

enhancement
2

First, many thanks for mockall. It's an awesome crate, it has become central to my (and my teams') development experience in Rust.

Not sure if this is possible to do, and I've missed how to do it in the documentation. If a trait has generic parameters, Rust allows a struct (or an enum) to implement multiple times for different parameter objects. How can I mock such an object?

Consider this example:

It gives the following error:

error[E0592]: duplicate definitions with name 'expect_value'

This example is derived from my use case: a "Context" object that acts as a centralized container/factory for several entities in my project. It implements a trait of the form Builder<E: Entity> for every of such entities. But I'm assuming there will be much less exotic use cases: think, for example, the From<T> standard trait.

Is there some way to mock an object like this? If there is, could you please point me to it? If not, looks like that an (opt-in) way of manually specifying the name of the "expect_" method would be enough:

garrettmaring

garrettmaring

enhancement
2

in the automock! documentation it is suggested to use mock! if "the autogenerated “MockFoo” name isn’t acceptable, and you want to choose your own name for the mock structure."

however, when I use mock! { pub MyStruct {} } i received an undeclared variable when trying to read MyStruct but it works when I change my import to use MockMyStruct.

how can I determine the name of the mocked structure using mock!?

taminomara

taminomara

enhancement
8

TLDR: I'm writing a crate that will allow mocking ethereum smart contracts, and I want it to work nicely with mockall. For that, I'd like to request making SeqHandle a part of official public API.

Longer explanation.

So, ethereum contracts are like structs (with data and methods) that live in a blockchain. I'm writing a crate that will allow mocking them without using an actual chain. The idea is that you create a mock blockchain and deploy mock contracts onto it. When you deploy a contract, you get an object for setting up expectations. Since we use mockall quite extensively in our projects, I've decided to mirror its API in this object:

Now I want to implement in_sequence, and I want it to work with mockall's native SeqHandle. This will allow creating sequences that combine calls to contracts and to normal mocked traits and functions.

chris-zen

chris-zen

question
5

I have not been able to compile the following mock (neither with mock! nor automock):

The error I see is:

I've tested both versions 0.9.1 and 0.10.0 (using rustc 1.53.0)

It seems like the macro misses to generate the lifetime 'a, and then the compiler complains about it being used in the where clause, but it doesn't complain about its use in other parts of the signature.

I'm pretty new to this library and I don't know where else to look at. Please let me know if you need further information to help with the identification of the problem. Thanks a lot ;-)

Sushisource

Sushisource

question
4

Hello, thanks so much for this library, super useful.

I have test setup code that will set a bunch of default expectations on mocks, but then some tests would like to alter the default expectations after the mock is built. Right now, if I just make another expect_foo call, that'll create an additional expectation, where I'd like it to actually replace the existing one. A nice way to do this might be something like a remove_expectations_foo method. Would this be a reasonable feature to add?

Thanks!

ChriFo

ChriFo

question
12

First of all: Thank you for a very useful library.

I have this (simplified) data structure:

And I use is it like that:

When trying to mock it like that:

The following error appears:

Thank you for any helpful information.

asomers

asomers

bug
0

The following to function signatures are equivalent, but Mockall will generated slightly different code for each:

In the former case, it will adjust the function signature to actually return X<'static>. In the latter the function signature won't be changed, but the expect_bar method will always return a 'static Expectation. Functionally, these two forms are nearly identical. However, the latter is more correct. In the former case, foo cannot be cast to a function pointer that has the same signature as the original, non-mock function.

Mockall should instead handle functions like foo by adjusting the signature to look like the equivalent bar.

These two patterns are demonstrated by the existing test cases mock_return_anonymous_lifetime.rs and mock_generic_method_returning_nonstatic.rs

asomers

asomers

enhancement
3

Currently Mockall cannot mock generic methods with non-static generic arguments. The reason is because arguments are downcast to Any and stored in a map. That allows the caller to set different expectations for different types, like this:

However, it also poses some problems. Chiefly, it's impossible to mock methods with non-'static generic arguments, because they can't be downcast. Also, it's difficult to mock arguments with unnameable or difficult-to-name argument types, like closures or futures.

An alternative may be possible: mock methods with generic arguments by turning those arguments into trait objects. That would skip downcasting. Most returning closures would be compatible; the argument's type would just change from concrete like &u32 to a trait object, like &dyn Debug. Also, the expect_foo method would no longer be generic. All expectations would be matched against all invocations.

There are other problems with this approach, however. Chiefly, not every type can be made into a trait object. Also, most trait objects wouldn't be useable with any of the predicate types. i.e., you wouldn't be able to do expect_foo().with(predicate::eq(42)). So I don't think this new technique could be made mandatory. Instead, it would probably have to be optional, opt-in with an attribute. Like this:

And of course, none of this applies to generic return values, only arguments.

ocboogie

ocboogie

5

I think it would be a great addition to add a return_const_once method to Expectation. It would work like a combination of return_once and return_const. The main reason I want this is so you could return a const without the value having to implement Clone.

An example where this would be useful: returning Result<Something + Clone, Error> where Error doesn't implement Clone but the function is only called once. As it is right now, this situation requires using return_once and cloning the value before hand. Whereas with this addition, you could simply do: mock.return_const_once(Ok(something.clone)). Although, there might be a simpler way now that I'm not aware of.

I'm happy to create a PR if this is a welcome addition.

e00E

e00E

enhancement
5

I saw in the changelog that you implemented support for async_trait. Thank you!

I noticed a limitation in this implementation. In the expectation we have to return a non future value. This prevents some advanced mocking from working:

This is an observable difference because async functions can either return their value or be pending. By only being able to return the values we cannot mock and test pending behavior. In the async { 1 } you can imagine that we want to be pending first for a short time (like sleeping, or waiting for a signal) and only then return the value. Or we get the value from an async channel.

These types of tests are probably rare and the current functionality is correct for most users but it might be nice to have. From an api perspective the most general solution is to have expect_foo always return a future so you would need to start an async block in the closure. I understand this is a little more work for users that don't need this but it is more correct. Alternatively there could be another postfix like returning_async but I'm not sure how this meshes with the existing _st. Or maybe mockall could detect whether returning on an async trait function expectation returns a normal value or a future. I don't know whether this is possible.

asomers

asomers

enhancement
0

Mockall currently requires that the closures passed to methods like returning are 'static. That's overly restrictive. The correct restriction should be that their lifetime is at least as great as the Expectation's. Likewise for the closures passed to methods like withf.

Information - Updated Dec 19, 2021

Stars: 619
Forks: 28
Issues: 14

Repositories & Extras

This library is a pull parser for CommonMark, written

Further, it optionally supports parsing footnotes,

This library is a pull parser for CommonMark, written

A library to create mocks out of structs

faux   mocks out of structs

A library to create mocks out of structs

Library for safe and correct Unix signal handling in Rust

Unix signals are inherently hard to handle correctly, for several reasons:

Library for safe and correct Unix signal handling in Rust

Library for traversing &amp; reading GameCube and Wii disc images

Based on the C++ library MIT license (LICENSE-MIT or

Library for traversing &amp; reading GameCube and Wii disc images

Library that implements low-level protocol to the Hitachi HD44780-compatible LCD device

by default (only uses 4 data pins) plus two control pins (R/S and EN)

Library that implements low-level protocol to the Hitachi HD44780-compatible LCD device

Library that implements low-level protocol to the Hitachi HD44780-compatible LCD device

by default (only uses 4 data pins) plus two control pins (R/S and EN)

Library that implements low-level protocol to the Hitachi HD44780-compatible LCD device
Http

265

HTTP mocking library for Rust

Advanced verification and debugging support

HTTP mocking library for Rust

Library crate for common tasks when building rust projects

Intended for use with cargo-auto

Library crate for common tasks when building rust projects
Facebook Instagram Twitter GitHub Dribbble
Privacy