{"id":13503160,"url":"https://github.com/DavidDeSimone/mock_derive","last_synced_at":"2025-03-29T13:30:52.335Z","repository":{"id":57639620,"uuid":"96493693","full_name":"DavidDeSimone/mock_derive","owner":"DavidDeSimone","description":"A mocking library for Rust-lang","archived":false,"fork":false,"pushed_at":"2020-10-28T03:16:21.000Z","size":127,"stargazers_count":57,"open_issues_count":1,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T20:49:28.333Z","etag":null,"topics":["crates","mock","mock-library","mocking","mocking-library","rust","rust-library","trait","unit-testing"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DavidDeSimone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-07T03:04:35.000Z","updated_at":"2024-12-29T03:40:19.000Z","dependencies_parsed_at":"2022-08-27T20:02:18.003Z","dependency_job_id":null,"html_url":"https://github.com/DavidDeSimone/mock_derive","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidDeSimone%2Fmock_derive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidDeSimone%2Fmock_derive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidDeSimone%2Fmock_derive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidDeSimone%2Fmock_derive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavidDeSimone","download_url":"https://codeload.github.com/DavidDeSimone/mock_derive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246190246,"owners_count":20737999,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crates","mock","mock-library","mocking","mocking-library","rust","rust-library","trait","unit-testing"],"created_at":"2024-07-31T22:02:39.521Z","updated_at":"2025-03-29T13:30:52.022Z","avatar_url":"https://github.com/DavidDeSimone.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"[![Follow us out on Crates.io](https://img.shields.io/crates/v/mock_derive.svg)](https://crates.io/crates/mock_derive)\n[![Build Status](https://travis-ci.org/DavidDeSimone/mock_derive.svg?branch=master)](https://travis-ci.org/DavidDeSimone/mock_derive)\n\nMock_Derive is an easy to setup, rich mocking library for the Rust programming language. It will allow you to quickly set up unit tests when leveraged with another testing system, like `cargo test`.\n\nIn order to install, just add this line to your Cargo.toml\n```\n[dependencies]\nmock_derive = \"0.8.0\"\n```\n\nAs a friendly note, mock_derive is not yet a 1.0 crate, and is still under heavy development. As such, you may find several real world use cases that are not yet supported. If you find such a case, please open an issue and we will look at it as soon as possible.\n\nmock_dervice was developed in 2017, however due to the life circumstance of the primary contributor, development was paused. In 2020, development has resumed. \n\n## How mock_derive is different to previous mocking libraries in other languages.\nIn traditional OO languages, mocking is usually based around inheritance, or a mix of method replacement in more dynamic languages. You make a `Foo` from a mock factory, define the behavior of that `Foo`, and pass it to functions expecting a `Foo`. Rust does not have traditional inheritance, meaning that *only a Foo is a Foo*. Mock_Derive encourages Implementation Mocking. This means that you will derive your mock for a trait. You will pass that mock to methods expecting something that implements that trait, and you will be able to control the behavior of that mock, similar to other mocking libs you may have worked with in the past.\n\n## Examples\nSee src/examples for working examples\n\nUsing this crate looks something like this: \n``` rust\n#![feature(proc_macro)]\nextern crate mock_derive;\n\nuse mock_derive::mock;\n\n#[mock]\npub trait CustomTrait {\n    fn get_int(\u0026self) -\u003e u32;\n    fn opt_int(\u0026self) -\u003e Option\u003cu32\u003e;\n    fn default_method(\u0026self, x: i32, y: i32) -\u003e i32 {\n        x + y\n    }\n}\n\n```\nYou'll notice that we have included a #[mock] directive above our trait definition. By default, this will generate an implementation of CustomTrait named \"MockCustomTrait\", that has helper functions used to control its behavior. For example, we can write the following test functions:\n \n``` rust\n#[test]\nfn it_works() {\n    let foo = Foo::new(); // Foo here is a struct that implements CustomTrait\n    let mut mock = MockCustomTrait::new();\n    mock.set_fallback(foo); // If a behavior isn't specified, we will fall back to this object's behavior.\n\n    let method = mock.method_get_int()\n        .first_call()\n        .set_result(3)\n        .second_call()\n        .set_result(4)\n\t.nth_call(3) // This is saying 'third_call'\n\t.set_result(5);\n\n\n    mock.set_get_int(method); // Due to Rust's ownership model, we will need to set our mock method\n                              // on our mock\n    let result = mock.get_int();\n    assert!(result == 3);\n    let result2 = mock.get_int();\n    assert!(result2 == 4);\n    let result3 = mock.get_int();\n    assert!(result3 == 5);\n\n    // This is a fallback case\n    let result4 = mock.get_int();\n    assert!(result4 == 1);\n}\n\n// You can also pass in a lambda to return a value. This can be used to return a value\n// an infinite number of times, or mutate state to simulate an object across calls.\n#[test]\nfn return_result_of() {\n    let mut x = 15;\n    let mut mock = MockCustomTrait::new();\n    let method = mock.method_opt_int()\n        .return_result_of(move || {\n            x += 1;\n            Some(x)\n        });\n\n    mock.set_opt_int(method);\n    assert!(mock.opt_int() == Some(16));\n    assert!(mock.opt_int() == Some(17));\n    assert!(mock.opt_int() == Some(18));\n}\n\n// You can also specify the total number of calls (i.e. once, exactly 5 times, at least 5 times, at most 10 times, etc.)\n#[test]\n// When using \"should panic\" it's suggested you look for specific errors\n#[should_panic(expected = \"called at least\")] \nfn min_calls_not_met() {\n    let mut mock = MockCustomTrait::new();\n    let method = mock.method_get_int()\n        .called_at_least(10)\n        .return_result_of(|| 10);\n    mock.set_foo(method);\n\n    for _ in 0..9 {\n        mock.get_int();\n    }\n}\n\n#[test]\nfn called_once() {\n    let mut mock = MockCustomTrait::new();\n    let method = mock.method_get_int()\n        .called_once()\n        .return_result_of(|| 10);\n    mock.set_foo(method);\n\n    mock.get_int(); // Commenting this line out would trigger a failure\n    // mock.get_int(); // This would trigger a failure\n}\n\n```\n## EXTERN FUNCTIONS\n\nAs of mock_derive 0.6.1, you can now mock static external functions. They share the same API as trait mocks. Check out tests/src/foriegn_functions.rs for more examples.\n\n``` rust\nuse mock_derive::mock;\n\n// In #[cfg(test)], this will generate functions named 'c_double', 'c_div', etc that you can control\n// the behavior of. When not in #[cfg(test)], #[mock] is a noop, meaning that no overhead is added,\n// and your program behaves as normal.\n#[mock]\nextern \"C\" {\n    pub fn c_double(x: isize) -\u003e isize;\n    pub fn c_div(x: isize, y: isize) -\u003e isize;\n    fn side_effect_fn(x: usize, y: usize);\n    fn no_args_no_ret();\n}\n\n#[mock]\nextern \"Rust\" {\n    fn x_double(x: isize) -\u003e isize;\n}\n\n#[test]\nfn extern_c_test() {\n    let mock = ExternCMocks::method_c_double()\n        .first_call()\n        .set_result(2);\n    \n    ExternCMocks::set_c_double(mock);\n    unsafe { assert!(c_double(1) == 2); }\n}\n\n#[test]\nfn extern_rust_test() {\n    let mock = ExternRustMocks::method_x_double()\n        .first_call()\n        .set_result(2);\n\n    ExternRustMocks::set_x_double(mock);\n    unsafe { assert!(x_double(1) == 2) };\n}\n\n```\n\n## GENERICS\n\nAs of mock_derive 0.5.0, we have (basic) support for generics. Check out tests/src/generics.rs for more examples.\n``` rust\n#[mock]\ntrait GenericTrait\u003cT, U\u003e\n      where T: Clone {\n      fn merge(\u0026self, t: T, u: U) -\u003e U;\n}\n\n#[test]\nfn generic_test_one() {\n    let mut mock = MockGenericTrait::\u003cf32, i32\u003e::new();\n    let method = mock.method_merge()\n        .called_once()\n        .set_result(30);\n\n    mock.set_merge(method);\n    assert!(mock.merge(15.0, 15) == 30);\n}\n\n#[mock]\ntrait LifetimeTrait\u003c'a, T\u003e\n    where T: 'a {\n    fn return_value(\u0026self, t: T) -\u003e \u0026'a T;\n}\n\nstatic TEST_FLOAT: f32 = 1.0;\n\n#[test]\nfn generics_and_lifetime() {\n    let mut mock = MockLifetimeTrait::\u003c'static, f32\u003e::new();\n    let method = mock.method_return_value()\n        .called_once()\n        .set_result(\u0026TEST_FLOAT);\n\n    mock.set_return_value(method);\n    assert!(mock.return_value(TEST_FLOAT.clone()) == \u0026TEST_FLOAT);\n}\n\n\n```\n\n## TESTING\nThere are some tests which double as examples in the tests/ directory. cd into that directory and run `cargo test`. \n\n## CONTRIBUTING\nAnyone is welcome to contribute! If you have an addition/bug fix that you would like to contribute, just open a PR and it will be looked at. Work in Progress (WIP) PRs are also welcome. Just include [WIP] in the name of the PR.\n\n## LICENSE\nMock_Derive is licensed under MIT. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDavidDeSimone%2Fmock_derive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDavidDeSimone%2Fmock_derive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDavidDeSimone%2Fmock_derive/lists"}