1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
<p>
<p align="center"><em>HTTP mocking for Rust!</em></p>
</p>
Mockito is a library for **generating and delivering HTTP mocks** in Rust. You can use it for integration testing
or offline work. Mockito runs a local pool of HTTP servers which create, deliver and remove the mocks.
## Features
- Supports HTTP1/2
- Runs your tests in parallel
- Comes with a wide range of request matchers (Regex, JSON, query parameters etc.)
- Checks that a mock was called (spy)
- Mocks multiple hosts at the same time
- Exposes sync and async interfaces
- Prints out a colored diff of the last unmatched request in case of errors
- Simple, intuitive API
- An awesome logo
The full documentation is available at <https://docs.rs/mockito>.
Before upgrading, make sure to check out the [changelog](https://github.com/lipanski/mockito/releases).
## Getting Started
Add `mockito` to your `Cargo.toml` and start mocking:
```rust
#[test]
fn test_something() {
// Request a new server from the pool
let mut server = mockito::Server::new();
// Use one of these addresses to configure your client
let host = server.host_with_port();
let url = server.url();
// Create a mock
let mock = server.mock("GET", "/hello")
.with_status(201)
.with_header("content-type", "text/plain")
.with_header("x-api-key", "1234")
.with_body("world")
.create();
// Any calls to GET /hello beyond this line will respond with 201, the
// `content-type: text/plain` header and the body "world".
// You can use `Mock::assert` to verify that your mock was called
mock.assert();
}
```
If `Mock::assert` fails, a colored diff of the last unmatched request is displayed:

Use **matchers** to handle requests to the same endpoint in a different way:
```rust
#[test]
fn test_something() {
let mut server = mockito::Server::new();
server.mock("GET", "/greetings")
.match_header("content-type", "application/json")
.match_body(mockito::Matcher::PartialJsonString(
"{\"greeting\": \"hello\"}".to_string(),
))
.with_body("hello json")
.create();
server.mock("GET", "/greetings")
.match_header("content-type", "application/text")
.match_body(mockito::Matcher::Regex("greeting=hello".to_string()))
.with_body("hello text")
.create();
}
```
Start **multiple servers** to simulate requests to different hosts:
```rust
#[test]
fn test_something() {
let mut twitter = mockito::Server::new();
let mut github = mockito::Server::new();
// These mocks will be available at `twitter.url()`
let twitter_mock = twitter.mock("GET", "/api").create();
// These mocks will be available at `github.url()`
let github_mock = github.mock("GET", "/api").create();
}
```
Write **async** tests (make sure to use the `_async` methods!):
```rust
#[tokio::test]
async fn test_simple_route_mock_async() {
let mut server = Server::new_async().await;
let m1 = server.mock("GET", "/a").with_body("aaa").create_async().await;
let m2 = server.mock("GET", "/b").with_body("bbb").create_async().await;
let (m1, m2) = futures::join!(m1, m2);
// You can use `Mock::assert_async` to verify that your mock was called
// m1.assert_async().await;
// m2.assert_async().await;
}
```
Start a **stand-alone server** on a dedicated port:
```rust
fn main() {
let opts = mockito::ServerOpts {
host: "0.0.0.0",
port: 1234,
..Default::default()
};
let mut server = mockito::Server::new_with_opts(opts);
let _m = server.mock("GET", "/").with_body("hello world").create();
loop {}
}
```
## Minimum supported Rust toolchain
The current minimum support Rust toolchain is **1.70.0**
## Contribution Guidelines
1. Check the existing issues and pull requests.
2. One commit is one feature - consider squashing.
3. Format code with `cargo fmt`.
4. :shipit:
## Development
### Tests
Run tests:
```sh
cargo test
```
...or run tests using a different toolchain:
```sh
rustup run --install 1.70.0 cargo test
```
...or run tests while disabling the default features (e.g. the colors):
```sh
cargo test --no-default-features
```
### Code style
Mockito uses [rustfmt](https://github.com/rust-lang/rustfmt) as a general code style.
Install `rustfmt`:
```sh
rustup component add rustfmt
```
Format code:
```sh
cargo fmt
```
Some editors might provide a plugin to format your Rust code automatically.
### Linter
Mockito uses [clippy](https://github.com/rust-lang/rust-clippy) and it should be run always on the minimum supported Rust version, in order to ensure backwards compatibility.
Install `clippy`:
```sh
rustup component add clippy
```
The linter is always run on the minimum supported Rust version:
```sh
rustup run --install 1.70.0 cargo clippy-mockito
```
### Release
Release:
```sh
cargo publish
```
### Benchmarks
Install `rust nightly`:
```sh
rustup install nightly
```
Run benchmarks:
```sh
rustup run nightly cargo bench
```
|