Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Le big rewrite #153

Merged
merged 1 commit into from
Feb 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[alias]
clippy-mockito = "clippy --lib --tests --all-features"
37 changes: 37 additions & 0 deletions .github/workflows/linters.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Linters

on:
push:
branches:
- master
pull_request:
branches:
- "*"

jobs:
rustfmt:
name: Run rustfmt on the minimum supported toolchain
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: 1.65.0
profile: minimal
components: clippy, rustfmt
override: true
- name: Run rustfmt
run: cargo fmt -- --check
clippy:
name: Run clippy on the minimum supported toolchain
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: 1.65.0
profile: minimal
components: clippy, rustfmt
override: true
- name: Run clippy
run: cargo clippy-mockito
56 changes: 56 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Tests

on:
push:
branches:
- master
pull_request:
branches:
- "*"

jobs:
test-default:
name: Test the minimum supported toolchain
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: 1.65.0
profile: minimal
override: true
- name: Check
run: cargo check
- name: Test
run: cargo test --no-default-features

test-latest:
name: Test on latest stable
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Check
run: cargo check
- name: Test
run: cargo test --no-default-features

test-nightly:
name: Test on nightly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
- name: Check
run: cargo check
- name: Test
run: cargo test --no-default-features

32 changes: 0 additions & 32 deletions .travis.yml

This file was deleted.

27 changes: 15 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,30 @@ description = "HTTP mocking for Rust."
keywords = ["mock", "mocks", "http", "webmock", "webmocks"]
categories = ["development-tools::testing", "web-programming"]
exclude = ["/.appveyor.yml", "/.travis.yml", "/benchmarks.txt", "/docs/", "/slides.pdf"]
edition = "2018"
edition = "2021"

[badges]
travis-ci = { repository = "lipanski/mockito", branch = "master" }
appveyor = { repository = "lipanski/mockito", branch = "master", service = "github" }

[dependencies]
assert-json-diff = "2.0"
async-trait = "0.1"
colored = { version = "2.0", optional = true }
deadpool = "0.9"
futures = "0.3"
hyper = { version = "0.14", features = ["full"] }
lazy_static = "1.4"
log = "0.4"
rand = "0.8"
httparse = "1.3.3"
regex = "1.0.5"
lazy_static = "1.1.0"
serde_json = "1.0.17"
similar = "2.1"

colored = { version = "2.0.0", optional = true }
log = "0.4.6"
assert-json-diff = "2.0.0"
serde_urlencoded = "0.7.0"
regex = "1.7"
serde_json = "1.0"
serde_urlencoded = "0.7"
similar = "2.2"
tokio = { version = "1.25", features = ["full"] }

[dev-dependencies]
env_logger = "0.8.2"
env_logger = "0.8"
testing_logger = "0.1"

[features]
Expand Down
117 changes: 105 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,117 @@
<p align="center">
<a href="https://docs.rs/mockito"><img src="https://docs.rs/mockito/badge.svg"></a>
<a href="https://crates.io/crates/mockito"><img src="https://img.shields.io/crates/v/mockito.svg"></a>
<img src="https://img.shields.io/badge/rust%20version-%3E%3D1.42.0-orange">
<img src="https://img.shields.io/badge/rust%20version-%3E%3D1.65.0-orange">
<a href="https://crates.io/crates/mockito"><img src="https://img.shields.io/crates/d/mockito"></a>
<a href="https://travis-ci.com/lipanski/mockito"><img src="https://travis-ci.com/lipanski/mockito.svg?branch=master"></a>
<a href="https://github.com/lipanski/mockito/actions/workflows/tests.yml/?branch=master"><img src="https://github.com/lipanski/mockito/actions/workflows/tests.yml/badge.svg?branch=master"></a>
<a href="https://ci.appveyor.com/project/lipanski/mockito"><img src="https://ci.appveyor.com/api/projects/status/github/lipanski/mockito?branch=master&svg=true"></a>
</p>
<p align="center"><em>HTTP mocking for Rust!</em></p>
</p>

Get it on [crates.io](https://crates.io/crates/mockito/).
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.

Documentation is available at <https://docs.rs/mockito>.
## Features

- Support for HTTP1/2
- Multi-threaded
- Various request matchers (Regex, JSON etc.)
- Mock multiple hosts at the same time
- Sync and async interface
- 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 m = 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
m.assert();
}
```

Use **matchers** to handle requests to the same endpoint in a different way:

```rust
#[test]
fn test_something() {
let mut server = mockito::Server::new();

let m1 = server.mock("GET", "/greetings")
.match_header("content-type", "application/json")
.match_body(mockito::Matcher::PartialJsonString(
"{\"greeting\": \"hello\"}".to_string(),
))
.with_body("hello json")
.create();

let m2 = 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:

```rust
#[tokio::test(flavor = "multi_thread")]
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();
let _m2 = server.mock("GET", "/b").with_body("bbb").create_async();

let (_m1, _m2) = futures::join!(_m1, _m2);
}
```

## Minimum supported Rust toolchain

The current minimum support Rust toolchain is **1.65.0**

## Contribution Guidelines

1. Check the existing issues and pull requests.
Expand All @@ -37,7 +134,7 @@ cargo test
...or run tests using a different toolchain:

```sh
rustup run --install 1.42.0 cargo test
rustup run --install 1.65.0 cargo test
```

...or run tests while disabling the default features (e.g. the colors):
Expand Down Expand Up @@ -71,13 +168,13 @@ Mockito uses [clippy](https://github.com/rust-lang/rust-clippy) and it should be
Install `clippy`:

```sh
rustup component add clippy-preview
rustup component add clippy
```

Run the linter on the minimum supported Rust version:
The linter is always run on the minimum supported Rust version:

```sh
rustup run --install 1.42.0 cargo clippy --lib --tests --all-features -- -D clippy::complexity
rustup run --install 1.65.0 cargo clippy-mockito
```

### Release
Expand All @@ -101,7 +198,3 @@ Run benchmarks:
```sh
rustup run nightly cargo bench
```

---

Logo courtesy to [http://niastudio.net](http://niastudio.net) :ok_hand:
21 changes: 11 additions & 10 deletions benches/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

extern crate test;

use mockito::{mock, reset, server_address};
use mockito::Server;
use std::fmt::Display;
use std::io::{BufRead, BufReader, Read, Write};
use std::net::TcpStream;
use std::str::FromStr;
use test::Bencher;

fn request_stream(route: &str, headers: &str) -> TcpStream {
let mut stream = TcpStream::connect(server_address()).unwrap();
fn request_stream(host: impl Display, route: &str, headers: &str) -> TcpStream {
let mut stream = TcpStream::connect(host.to_string()).unwrap();
let message = [route, " HTTP/1.1\r\n", headers, "\r\n"].join("");
stream.write_all(message.as_bytes()).unwrap();

Expand Down Expand Up @@ -49,27 +50,27 @@ fn parse_stream(stream: TcpStream) -> (String, Vec<String>, String) {
(status_line, headers, body)
}

fn request(route: &str, headers: &str) -> (String, Vec<String>, String) {
parse_stream(request_stream(route, headers))
fn request(host: impl Display, route: &str, headers: &str) -> (String, Vec<String>, String) {
parse_stream(request_stream(host, route, headers))
}

#[bench]
fn bench_create_simple_mock(b: &mut Bencher) {
reset();
let mut s = Server::new();

b.iter(|| {
let _m = mock("GET", "/").with_body("test").create();
let _m = s.mock("GET", "/").with_body("test").create();
})
}

#[bench]
fn bench_match_simple_mock(b: &mut Bencher) {
reset();
let mut s = Server::new();

let _m = mock("GET", "/").with_body("test").create();
let _m = s.mock("GET", "/").with_body("test").create();

b.iter(|| {
let (status_line, _, _) = request("GET /", "");
let (status_line, _, _) = request(&s.host_with_port(), "GET /", "");
assert!(status_line.starts_with("HTTP/1.1 200"));
})
}
4 changes: 3 additions & 1 deletion examples/mockito-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use mockito;
use std::time::Duration;

fn main() {
mockito::start();
let mut s = mockito::Server::new();

s.mock("GET", "/").with_body("hello world");

loop {
std::thread::sleep(Duration::from_secs(1))
Expand Down
2 changes: 2 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
edition = "2021"
max_width = 100
Loading