├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── crates_io_readme.md ├── logo.png ├── logo.svg ├── macros ├── Cargo.toml ├── crates_io_readme.md └── src │ ├── display_delegate.rs │ ├── header_builder.rs │ ├── item_injector.rs │ └── lib.rs ├── rust-toolchain ├── src ├── lib.rs ├── mock_store.rs ├── mocking.rs └── mocking_utils.rs └── tests ├── injecting.rs ├── injecting_no_std.rs ├── mocking.rs ├── mocking_fns ├── mod.rs ├── when_fn_generic.rs ├── when_fn_generic_async.rs ├── when_fn_regular.rs └── when_fn_regular_async.rs ├── mocking_methods ├── mod.rs ├── when_struct_generic_method_generic.rs ├── when_struct_generic_method_regular.rs ├── when_struct_regular_method_generic.rs └── when_struct_regular_method_regular.rs ├── mocking_methods_async ├── mod.rs ├── when_struct_complex_method_regular_async.rs ├── when_struct_generic_method_generic_async.rs ├── when_struct_generic_method_regular_async.rs ├── when_struct_regular_method_generic_async.rs └── when_struct_regular_method_regular_async.rs ├── mocking_trait_defaults ├── mod.rs ├── when_trait_generic_struct_generic_method_generic.rs ├── when_trait_generic_struct_generic_method_regular.rs ├── when_trait_generic_struct_regular_method_generic.rs ├── when_trait_generic_struct_regular_method_regular.rs ├── when_trait_regular_struct_generic_method_generic.rs ├── when_trait_regular_struct_generic_method_regular.rs ├── when_trait_regular_struct_regular_method_generic.rs └── when_trait_regular_struct_regular_method_regular.rs ├── mocking_traits ├── mod.rs ├── when_trait_generic_struct_generic_method_generic.rs ├── when_trait_generic_struct_generic_method_regular.rs ├── when_trait_generic_struct_regular_method_generic.rs ├── when_trait_generic_struct_regular_method_regular.rs ├── when_trait_regular_struct_generic_method_generic.rs ├── when_trait_regular_struct_generic_method_regular.rs ├── when_trait_regular_struct_regular_method_generic.rs └── when_trait_regular_struct_regular_method_regular.rs └── module_annotated_declaration └── mod.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | 5 | .idea 6 | *.iml 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - nightly 4 | before_script: 5 | - rustup component add rustfmt --toolchain nightly 6 | script: 7 | - cargo fmt --all -- --check 8 | - cargo test 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.7.9 - 2020-12-22 2 | - Check all method call args in substitution 3 | ## 0.7.8 - 2020-12-22 4 | - Fix async self substitution for call 5 | ## 0.7.7 - 2020-12-22 6 | - Transform async method with local binding 7 | - Fix missing lifetimes on async method refs 8 | ## 0.7.6 - 2020-10-23 9 | - Transform all async methods 10 | ## 0.7.5 - 2019-11-22 11 | - Fix regression from 0.7.4 12 | - Fix potential name clash in generated code 13 | - Upgrade syn, quote and proc-macro2 to 1.0 14 | - Clean up macro code 15 | ## 0.7.4 - 2019-11-17 16 | - Fix UB while copying function input parameters (thank you @artemii235!) 17 | ## 0.7.3 - 2019-07-23 18 | - Fix warnings and UB on newer compilers 19 | ## 0.7.2 - 2019-06-14 20 | - Add MockContext (thank you @czipperz!) 21 | ## 0.7.1 - 2019-05-24 22 | - Add function for clearing all mocks (thank you @clinedome-work!) 23 | ## 0.7.0 - 2019-02-13 24 | - Allow mock closures to call mockable and mocked functions and to create mocks 25 | - Make functions not mocked during execution of their mock closures to prevent recursive calls 26 | - Accept inability to inject modules in separate files: remove tests and fix docs 27 | - Upgrade project to Rust 2018 28 | - Add mocking tricks to docs 29 | ## 0.6.0 - 2019-02-09 30 | - Fix for rustc 1.31.0-nightly (ad6e5c003 2018-09-28) and newer (thank you @asomers and @rye!) 31 | ## 0.5.0 - 2018-07-17 32 | - Fix for rustc 1.29.0-nightly (1ecf6929d 2018-07-16) and newer 33 | ## 0.4.1 - 2018-07-15 34 | - Fix tests for rustc 1.29.0-nightly (254f8796b 2018-07-13) and newer 35 | ## 0.4.0 - 2018-05-23 36 | - Port to rustc 1.28.0-nightly (71e87be38 2018-05-22) and newer 37 | ## 0.3.8 - 2018-05-13 38 | - Add mocking with mutable closure 39 | ## 0.3.7 - 2018-05-13 40 | - Fix uninitialized memory access when fn arg has drop and mock returns continue 41 | - Fix specific case of injecting trait impl 42 | ## 0.3.6 - 2018-05-11 43 | - Fix injecting of fns with unused generics 44 | - Prevent injecting of Drop::drop 45 | - Upgrade minimum Syn version to 0.13.7 46 | ## 0.3.5 - 2018-05-08 47 | - Enable mocking of code in a no_std crate when std lib is available 48 | ## 0.3.4 - 2018-05-06 49 | - Make annotating items unparsable for Syn raise warning and continue without making it mockable instead of failing whole compilation 50 | ## 0.3.3 - 2018-05-04 51 | - Prevent macros from injecting unsafe functions, which would make them uncompilable 52 | ## 0.3.2 - 2018-05-04 53 | - Fix segfault when fn arg has drop and mock is returned 54 | - Fix returning mocks of generic types, which was broken in version 0.3.1 55 | ## 0.3.1 - 2018-05-03 56 | - Fix injecting trait impls when return type has longer lifetime than required by trait 57 | ## 0.3.0 - 2018-04-30 58 | - Upgrade syn to 0.13.4 and make it use nightly features of proc-macro2. This lets compiler correctly point at errors in injected functions, which closes issue #5. 59 | ## 0.2.1 - 2018-04-29 60 | - Add support for proc_macros feature being split up into proc_macros and proc_macro_mod in Rust nightly from 2018-04-27 61 | ## 0.2.0 - 2018-01-23 62 | - Migrate Mocktopus macros from Syn 0.11 to 0.12 63 | ## 0.1.2 - 2018-01-23 64 | - Panicking inside mock code does not cause dropping of uninitialized memory 65 | - Items with two `#[mockable]` attributes on them are not injected twice 66 | extern crate mocktopus can be now aliased 67 | ## 0.1.1 - 2017-09-05 68 | - Remove Cargo.lock, add logo in macro docs and bump version to 0.1.1 69 | ## 0.1.0 - 2017-09-05 70 | - Remove Cargo.lock, add logo in macro docs and bump version to 0.1.1 71 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mocktopus" 3 | version = "0.8.0" 4 | authors = [ 5 | "CodeSandwich ", 6 | "gregdhill " 7 | ] 8 | description = "Mocking framework for Rust" 9 | readme = "crates_io_readme.md" 10 | keywords = ["testing", "mocking", "tdd"] 11 | categories = ["development-tools::testing"] 12 | repository = "https://github.com/CodeSandwich/Mocktopus" 13 | license = "MIT" 14 | exclude = ["logo.png", "logo.svg"] 15 | edition = "2018" 16 | 17 | [badges] 18 | travis-ci = { repository = "CodeSandwich/Mocktopus" } 19 | 20 | [lib] 21 | doctest = false 22 | 23 | [dependencies] 24 | mocktopus_macros = "0.7.11" 25 | 26 | [dev-dependencies] 27 | tokio = { version = "0.2", features = ["full"] } 28 | 29 | [workspace] 30 | members = ["macros"] 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Crates.io](https://img.shields.io/crates/d/mocktopus.svg)](https://crates.io/crates/mocktopus) 2 | [![Docs.rs](https://docs.rs/mocktopus/badge.svg)](https://docs.rs/crate/mocktopus) 3 | [![Build Status](https://travis-ci.org/CodeSandwich/Mocktopus.svg?branch=master)](https://travis-ci.org/CodeSandwich/Mocktopus) 4 | 5 |

6 | logo 7 |

8 | 9 | Mocking framework for Rust (currently only nightly). See [documentation](https://docs.rs/mocktopus/) for more. 10 | 11 | ```rust 12 | #[mockable] 13 | mod hello_world { 14 | pub fn world() -> &'static str { 15 | "world" 16 | } 17 | 18 | pub fn hello_world() -> String { 19 | format!("Hello {}!", world()) 20 | } 21 | } 22 | 23 | #[test] 24 | fn mock_test() { 25 | hello_world::world.mock_safe(|| MockResult::Return("mocking")); 26 | 27 | assert_eq!("Hello mocking!", hello_world::hello_world()); 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /crates_io_readme.md: -------------------------------------------------------------------------------- 1 | ![logo](https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png) 2 | 3 | Mocking framework for Rust (currently only nightly). See [documentation](https://docs.rs/mocktopus/) for more. 4 | 5 | ```rust 6 | #[mockable] 7 | mod hello_world { 8 | pub fn world() -> &'static str { 9 | "world" 10 | } 11 | 12 | pub fn hello_world() -> String { 13 | format!("Hello {}!", world()) 14 | } 15 | } 16 | 17 | #[test] 18 | fn mock_test() { 19 | hello_world::world.mock_safe(|| MockResult::Return("mocking")); 20 | 21 | assert_eq!("Hello mocking!", hello_world::hello_world()); 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeSandwich/Mocktopus/aec15b3c03d81c143503b9e72b6a5b03a009e2e2/logo.png -------------------------------------------------------------------------------- /macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mocktopus_macros" 3 | version = "0.7.11" 4 | authors = [ 5 | "CodeSandwich ", 6 | "gregdhill " 7 | ] 8 | description = "Mocktopus procedural macros" 9 | readme = "crates_io_readme.md" 10 | repository = "https://github.com/CodeSandwich/Mocktopus" 11 | license = "MIT" 12 | edition = "2018" 13 | 14 | [lib] 15 | proc-macro = true 16 | doctest = false 17 | 18 | [dependencies] 19 | syn = { version = "1.0", features = ["full"] } 20 | quote = "1.0" 21 | proc-macro2 = "1.0" 22 | -------------------------------------------------------------------------------- /macros/crates_io_readme.md: -------------------------------------------------------------------------------- 1 | [Mocktopus](https://crates.io/crates/mocktopus) procedural macros making items mockable 2 | -------------------------------------------------------------------------------- /macros/src/display_delegate.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{Display, Error, Formatter}; 2 | 3 | pub struct DisplayDelegate Result<(), Error>> { 4 | delegate: T, 5 | } 6 | 7 | impl Result<(), Error>> DisplayDelegate { 8 | fn new(delegate: T) -> Self { 9 | DisplayDelegate { delegate } 10 | } 11 | } 12 | 13 | impl Result<(), Error>> Display for DisplayDelegate { 14 | fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> { 15 | (self.delegate)(formatter) 16 | } 17 | } 18 | 19 | pub fn display Result<(), Error>>(to_display: T) -> DisplayDelegate { 20 | DisplayDelegate::new(to_display) 21 | } 22 | -------------------------------------------------------------------------------- /macros/src/header_builder.rs: -------------------------------------------------------------------------------- 1 | use crate::display_delegate::display; 2 | use proc_macro2::{Group, Span, TokenTree}; 3 | use quote::ToTokens; 4 | use std::fmt::{Error, Formatter}; 5 | use syn::punctuated::Punctuated; 6 | use syn::token::{Colon2, Semi}; 7 | use syn::{ 8 | self, Expr, ExprUnsafe, FnArg, GenericParam, Pat, PatIdent, PatType, PathSegment, Signature, 9 | Stmt, 10 | }; 11 | 12 | const MOCKTOPUS_CRATE_NAME: &str = "__mocktopus_crate__"; 13 | const STD_CRATE_NAME: &str = "__mocktopus_std__"; 14 | const ARGS_TO_CONTINUE_NAME: &str = "__mocktopus_args_to_continue__"; 15 | const ARGS_TO_RETURN_NAME: &str = "__mocktopus_args_to_return__"; 16 | const UNWIND_DATA_NAME: &str = "__mocktopus_unwind_data__"; 17 | 18 | macro_rules! error_msg { 19 | ($msg:expr) => { 20 | concat!("Mocktopus internal error: ", $msg) 21 | }; 22 | } 23 | 24 | pub enum FnHeaderBuilder<'a> { 25 | StaticFn, 26 | StructImpl, 27 | TraitDefault, 28 | TraitImpl(&'a Punctuated), 29 | } 30 | 31 | impl<'a> FnHeaderBuilder<'a> { 32 | pub fn build(&self, fn_decl: &Signature, fn_block_span: Span) -> Stmt { 33 | let fn_args = &fn_decl.inputs; 34 | let header_str = format!( 35 | r#"unsafe {{ 36 | extern crate mocktopus as {mocktopus}; 37 | extern crate std as {std_crate}; 38 | match {std_crate}::panic::catch_unwind({std_crate}::panic::AssertUnwindSafe ( 39 | || {mocktopus}::mocking::Mockable::call_mock(&{full_fn_name}, {extract_args}))) {{ 40 | Ok({mocktopus}::mocking::MockResult::Continue(mut {args_to_continue})) => {restore_args}, 41 | Ok({mocktopus}::mocking::MockResult::Return({args_to_return})) => {{ 42 | {forget_args} 43 | let returned = {std_crate}::mem::transmute_copy(&{args_to_return}); 44 | {std_crate}::mem::forget({args_to_return}); 45 | return returned; 46 | }}, 47 | Err({unwind}) => {{ 48 | {forget_args} 49 | {std_crate}::panic::resume_unwind({unwind}); 50 | }}, 51 | }} 52 | }}"#, 53 | mocktopus = MOCKTOPUS_CRATE_NAME, 54 | std_crate = STD_CRATE_NAME, 55 | full_fn_name = display(|f| write_full_fn_name(f, self, fn_decl)), 56 | extract_args = display(|f| write_extract_args(f, fn_args)), 57 | args_to_continue = ARGS_TO_CONTINUE_NAME, 58 | args_to_return = ARGS_TO_RETURN_NAME, 59 | restore_args = display(|f| write_restore_args(f, fn_args)), 60 | forget_args = display(|f| write_forget_args(f, fn_args)), 61 | unwind = UNWIND_DATA_NAME 62 | ); 63 | let header_block = syn::parse_str::(&header_str) 64 | .expect(error_msg!("generated header unparsable")); 65 | create_call_site_spanned_stmt(header_block, fn_block_span) 66 | } 67 | } 68 | 69 | fn create_call_site_spanned_stmt(block: impl ToTokens, span: Span) -> Stmt { 70 | let token_stream = block 71 | .into_token_stream() 72 | .into_iter() 73 | .map(|tt| make_token_tree_span_call_site(tt, span)) 74 | .collect(); 75 | Stmt::Semi(Expr::Verbatim(token_stream), Semi { spans: [span] }) 76 | } 77 | 78 | fn make_token_tree_span_call_site(mut token_tree: TokenTree, span: Span) -> TokenTree { 79 | token_tree.set_span(span); 80 | if let TokenTree::Group(ref mut group) = token_tree { 81 | let tokens = group 82 | .stream() 83 | .into_iter() 84 | .map(|tt| make_token_tree_span_call_site(tt, span)) 85 | .collect(); 86 | *group = Group::new(group.delimiter(), tokens); 87 | } 88 | token_tree 89 | } 90 | 91 | fn write_full_fn_name( 92 | f: &mut Formatter, 93 | builder: &FnHeaderBuilder, 94 | fn_decl: &Signature, 95 | ) -> Result<(), Error> { 96 | match *builder { 97 | FnHeaderBuilder::StaticFn => (), 98 | FnHeaderBuilder::StructImpl | FnHeaderBuilder::TraitDefault => write!(f, "Self::")?, 99 | FnHeaderBuilder::TraitImpl(ref path) => { 100 | write!(f, "::", display(|f| write_trait_path(f, path)))? 101 | } 102 | } 103 | write!( 104 | f, 105 | "{}::<{}>", 106 | fn_decl.ident, 107 | display(|f| write_fn_generics(f, fn_decl)) 108 | ) 109 | } 110 | 111 | fn write_trait_path( 112 | f: &mut Formatter, 113 | path: &Punctuated, 114 | ) -> Result<(), Error> { 115 | write!(f, "{}", path.into_token_stream()) 116 | } 117 | 118 | fn write_fn_generics(f: &mut Formatter, fn_decl: &Signature) -> Result<(), Error> { 119 | fn_decl 120 | .generics 121 | .params 122 | .iter() 123 | .filter_map(get_generic_param_name) 124 | .map(|param| write!(f, "{},", param)) 125 | .collect() 126 | } 127 | 128 | fn get_generic_param_name(param: &GenericParam) -> Option { 129 | match *param { 130 | GenericParam::Type(ref type_param) => Some(type_param.ident.to_string()), 131 | _ => None, 132 | } 133 | } 134 | 135 | fn write_extract_args(f: &mut Formatter, fn_args: &Punctuated) -> Result<(), Error> { 136 | if fn_args.is_empty() { 137 | return write!(f, "()"); 138 | } 139 | write!(f, "(")?; 140 | for fn_arg_name in iter_fn_arg_names(fn_args) { 141 | write!( 142 | f, 143 | "{}::mem::transmute_copy(&{}), ", 144 | STD_CRATE_NAME, fn_arg_name 145 | )?; 146 | } 147 | write!(f, ")") 148 | } 149 | 150 | fn write_restore_args(f: &mut Formatter, fn_args: &Punctuated) -> Result<(), Error> { 151 | if fn_args.is_empty() { 152 | return writeln!(f, "()"); 153 | } 154 | writeln!(f, "{{")?; 155 | for (fn_arg_index, fn_arg_name) in iter_fn_arg_names(fn_args).enumerate() { 156 | writeln!( 157 | f, 158 | "{}::mem::swap(&mut *(&{} as *const _ as *mut _), &mut {}.{});", 159 | STD_CRATE_NAME, fn_arg_name, ARGS_TO_CONTINUE_NAME, fn_arg_index 160 | )?; 161 | } 162 | writeln!( 163 | f, 164 | "{}::mem::forget({});", 165 | STD_CRATE_NAME, ARGS_TO_CONTINUE_NAME 166 | )?; 167 | writeln!(f, "}}") 168 | } 169 | 170 | fn write_forget_args(f: &mut Formatter, fn_args: &Punctuated) -> Result<(), Error> { 171 | for fn_arg_name in iter_fn_arg_names(fn_args) { 172 | writeln!(f, "{}::mem::forget({});", STD_CRATE_NAME, fn_arg_name)?; 173 | } 174 | Ok(()) 175 | } 176 | 177 | fn iter_fn_arg_names<'a, T>( 178 | input_args: &'a Punctuated, 179 | ) -> impl Iterator + 'a { 180 | input_args.iter().map(|fn_arg| { 181 | match fn_arg { 182 | FnArg::Receiver(_) => return "self".to_string(), 183 | FnArg::Typed(PatType { pat, .. }) => { 184 | if let Pat::Ident(PatIdent { ident, .. }) = &**pat { 185 | return ident.to_string(); 186 | } 187 | } 188 | }; 189 | panic!( 190 | "{}: '{}'", 191 | error_msg!("invalid fn arg type"), 192 | fn_arg.clone().into_token_stream() 193 | ) 194 | }) 195 | } 196 | -------------------------------------------------------------------------------- /macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! [Mocktopus](https://docs.rs/mocktopus) procedural macros making items mockable 2 | #![doc( 3 | html_logo_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png", 4 | html_favicon_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png" 5 | )] 6 | #![feature(proc_macro_diagnostic)] 7 | 8 | extern crate proc_macro; 9 | 10 | mod display_delegate; 11 | mod header_builder; 12 | mod item_injector; 13 | 14 | use proc_macro::{Span, TokenStream}; 15 | use quote::ToTokens; 16 | 17 | /// Procedural macro, makes items and their sub-items mockable 18 | /// 19 | /// # Valid to annotate 20 | /// - module definitions (makes all its valid to annotate items annotated) 21 | /// 22 | /// ``` 23 | /// #[mockable] 24 | /// mod module { 25 | /// mod nested { 26 | /// fn mockable() { ... } 27 | /// } 28 | /// } 29 | /// ``` 30 | /// - standalone functions 31 | /// 32 | /// ``` 33 | /// #[mockable] 34 | /// fn mockable() { ... } 35 | /// ``` 36 | /// - struct impl blocks (makes all functions inside mockable) 37 | /// 38 | /// ``` 39 | /// #[mockable] 40 | /// impl Structure { 41 | /// fn mockable() { ... } 42 | /// } 43 | /// ``` 44 | /// - trait impl blocks (makes all functions inside mockable) 45 | /// 46 | /// ``` 47 | /// #[mockable] 48 | /// impl Trait for Structure { 49 | /// fn mockable() { ... } 50 | /// } 51 | /// ``` 52 | /// - traits (makes all default functions inside mockable) 53 | /// 54 | /// ``` 55 | /// #[mockable] 56 | /// trait Trait { 57 | /// fn mockable() { ... } 58 | /// } 59 | /// ``` 60 | /// # Invalid to annotate **(WILL FAIL TO COMPILE OR BREAK MOCKING!)** 61 | /// 62 | /// - single functions in struct impls 63 | /// 64 | /// ``` 65 | /// impl Structure { 66 | /// #[mockable] //INVALID USAGE! 67 | /// fn mockable() { ... } 68 | /// } 69 | /// ``` 70 | /// - single functions in trait impls 71 | /// 72 | /// ``` 73 | /// impl Trait for Structure { 74 | /// #[mockable] //INVALID USAGE! 75 | /// fn mockable() { ... } 76 | /// } 77 | /// ``` 78 | /// - single default functions in traits 79 | /// 80 | /// ``` 81 | /// trait Trait { 82 | /// #[mockable] //INVALID USAGE! 83 | /// fn mockable() { ... } 84 | /// } 85 | /// ``` 86 | /// # Indifferent to annotate 87 | /// - already mockable items (inside annotated modules) 88 | /// - module declarations 89 | /// 90 | /// ``` 91 | /// #[mockable] 92 | /// mod module; 93 | /// ``` 94 | /// - const functions (they are impossible to mock) 95 | /// - unsafe functions (they are impossible to mock) 96 | /// - any macro generated items (they are impossible to mock) 97 | /// - any other items 98 | #[proc_macro_attribute] 99 | pub fn mockable(_: TokenStream, token_stream: TokenStream) -> TokenStream { 100 | let mut item: syn::Item = match syn::parse(token_stream.clone()) { 101 | Ok(item) => item, 102 | Err(err) => { 103 | Span::call_site() 104 | .warning("Failed to make code mockable") 105 | .error(format!("Failed to parse: {}", err)) 106 | .emit(); 107 | return token_stream; 108 | } 109 | }; 110 | item_injector::inject_item(&mut item); 111 | item.into_token_stream().into() 112 | } 113 | 114 | /// Procedural macro, guards items from being made mockable by enclosing item. 115 | /// 116 | /// # Valid to annotate 117 | /// - module definitions 118 | /// 119 | /// ``` 120 | /// #[mockable] 121 | /// mod module { 122 | /// #[not_mockable] 123 | /// mod nested { 124 | /// fn not_mockable() { ... } 125 | /// } 126 | /// } 127 | /// ``` 128 | /// - standalone functions 129 | /// 130 | /// ``` 131 | /// #[mockable] 132 | /// mod module { 133 | /// #[not_mockable] 134 | /// fn not_mockable() { ... } 135 | /// } 136 | /// ``` 137 | /// - struct impl blocks 138 | /// 139 | /// ``` 140 | /// #[mockable] 141 | /// mod module { 142 | /// #[not_mockable] 143 | /// impl Struct { 144 | /// fn not_mockable() { ... } 145 | /// } 146 | /// } 147 | /// ``` 148 | /// - trait impl blocks 149 | /// 150 | /// ``` 151 | /// #[mockable] 152 | /// mod module { 153 | /// #[not_mockable] 154 | /// impl Trait for Struct { 155 | /// fn not_mockable() { ... } 156 | /// } 157 | /// } 158 | /// ``` 159 | /// - traits 160 | /// 161 | /// ``` 162 | /// #[mockable] 163 | /// mod module { 164 | /// #[not_mockable] 165 | /// trait Trait { 166 | /// fn not_mockable() { ... } 167 | /// } 168 | /// } 169 | /// ``` 170 | /// - single functions in struct impls 171 | /// 172 | /// ``` 173 | /// #[mockable] 174 | /// impl Struct { 175 | /// #[not_mockable] 176 | /// fn not_mockable() { ... } 177 | /// } 178 | /// ``` 179 | /// - single functions in trait impls 180 | /// 181 | /// ``` 182 | /// #[mockable] 183 | /// impl Trait for Struct { 184 | /// #[not_mockable] 185 | /// fn not_mockable() { ... } 186 | /// } 187 | /// ``` 188 | /// - single default functions in traits 189 | /// 190 | /// ``` 191 | /// #[mockable] 192 | /// trait Trait { 193 | /// #[not_mockable] 194 | /// fn not_mockable() { ... } 195 | /// } 196 | /// ``` 197 | /// 198 | /// # Indifferent to annotate 199 | /// - items not made mockable by enclosing item 200 | /// - any other items 201 | #[proc_macro_attribute] 202 | pub fn not_mockable(_: TokenStream, token_stream: TokenStream) -> TokenStream { 203 | token_stream 204 | } 205 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly 2 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(fn_traits, tuple_trait, unboxed_closures)] 2 | 3 | //! Mocking framework for Rust (currently only nightly) 4 | //! 5 | //! ``` 6 | //! #[mockable] 7 | //! mod hello_world { 8 | //! pub fn world() -> &'static str { 9 | //! "world" 10 | //! } 11 | //! 12 | //! pub fn hello_world() -> String { 13 | //! format!("Hello {}!", world()) 14 | //! } 15 | //! } 16 | //! 17 | //! #[test] 18 | //! fn mock_test() { 19 | //! hello_world::world.mock_safe(|| MockResult::Return("mocking")); 20 | //! 21 | //! assert_eq!("Hello mocking!", hello_world::hello_world()); 22 | //! } 23 | //! ``` 24 | //! # Introduction 25 | //! This is a user guide showing Rust project set up for testing with mocks. 26 | //! 27 | //! It is highly recommended to **use mocks ONLY for test runs and NEVER in release builds!** 28 | //! Mocktopus is not designed for high performance and will slow down code execution. 29 | //! 30 | //! Note: this guide shows set up of mocking for test builds only. 31 | //! # Prerequisites 32 | //! Add Mocktopus dev-dependency to project's `Cargo.toml`: 33 | //! 34 | //! ``` 35 | //! [dev-dependencies] 36 | //! mocktopus = "0.7.0" 37 | //! ``` 38 | //! Enable procedural macros in crate root: 39 | //! 40 | //! ``` 41 | //! #![cfg_attr(test, feature(proc_macro_hygiene))] 42 | //! ``` 43 | //! Import Mocktopus (skip for Rust 2018): 44 | //! 45 | //! ``` 46 | //! #[cfg(test)] 47 | //! extern crate mocktopus; 48 | //! ``` 49 | //! # Making functions mockable 50 | //! To make functions mockable they must be annotated with provided procedural macros. 51 | //! See [documentation](https://docs.rs/mocktopus_macros) for all their possibilities and rules. 52 | //! 53 | //! To use these macros import them into namespace: 54 | //! 55 | //! ``` 56 | //! #[cfg(test)] 57 | //! use mocktopus::macros::*; 58 | //! ``` 59 | //! Annotate mockable code like standalone functions or impl blocks: 60 | //! 61 | //! ``` 62 | //! #[mockable] 63 | //! fn my_fn() {} 64 | //! 65 | //! #[mockable] 66 | //! impl Struct { 67 | //! fn my_method() {} 68 | //! } 69 | //! ``` 70 | //! It's NOT legal to annotate single funciton in impl block: 71 | //! 72 | //! ``` 73 | //! impl Struct { 74 | //! #[mockable] // WRONG, will break Mocktopus 75 | //! fn my_method() {} 76 | //! } 77 | //! ``` 78 | //! It is possible to annotate modules, which makes all their potentially mockable content mockable: 79 | //! 80 | //! ``` 81 | //! #[cfg_attr(test, mockable)] 82 | //! mod my_module { 83 | //! fn my_fn() {} 84 | //! } 85 | //! ``` 86 | //! This does NOT work for modules in separate file: 87 | //! 88 | //! ``` 89 | //! #[cfg_attr(test, mockable)] // WRONG, has no effect 90 | //! mod my_module; 91 | //! ``` 92 | //! # Mocking 93 | //! Import tools for mocking in test module: 94 | //! 95 | //! ``` 96 | //! #[cfg(test)] 97 | //! mod tests { 98 | //! use mocktopus::mocking::*; 99 | //! ``` 100 | //! Among others this imports trait `Mockable`. 101 | //! It is implemented for all functions and provides an interface for setting up mocks: 102 | //! 103 | //! ``` 104 | //! #[test] 105 | //! fn my_test() { 106 | //! my_function.mock_safe(|| MockResult::Return(1)); 107 | //! 108 | //! assert_eq!(1, my_function()); 109 | //! } 110 | //! ``` 111 | //! It is also possible to mock struct methods, either from own impls, traits or trait defaults: 112 | //! 113 | //! ``` 114 | //! // Mocking method 115 | //! MyStruct::my_method.mock_safe(|| MockResult::Return(1)); 116 | //! // Mocking trait method 117 | //! MyStruct::my_trait_method.mock_safe(|| MockResult::Return(2)); 118 | //! // Mocking default trait method 119 | //! MyStruct::my_trait_default_method.mock_safe(|| MockResult::Return(3)); 120 | //! ``` 121 | //! Mocking with `mock_safe` is simplest, but the `Mockable` trait has more, 122 | //! see [documantation](mocking/trait.Mockable.html). 123 | //! 124 | //! ## Mocking range 125 | //! Every mock works only in thread, in which it was set. 126 | //! All Rust test runs are executed in independent threads, so mocks do not leak between them: 127 | //! 128 | //! ``` 129 | //! #[cfg_attr(test, mockable)] 130 | //! fn common_fn() -> u32 { 131 | //! 0 132 | //! } 133 | //! 134 | //! #[test] 135 | //! fn common_fn_test_1() { 136 | //! assert_eq!(0, common_fn()); 137 | //! 138 | //! common_fn.mock_safe(|| MockResult::Return(1)); 139 | //! 140 | //! assert_eq!(1, common_fn()); 141 | //! } 142 | //! 143 | //! #[test] 144 | //! fn common_fn_test_2() { 145 | //! assert_eq!(0, common_fn()); 146 | //! 147 | //! common_fn.mock_safe(|| MockResult::Return(2)); 148 | //! 149 | //! assert_eq!(2, common_fn()); 150 | //! } 151 | //! ``` 152 | //! 153 | //! ## Mock closure 154 | //! `mock_safe` has single argument: a closure, which takes same input as mocked function and returns a `MockResult`. 155 | //! Whenever the mocked function is called, its inputs are passed to the closure: 156 | //! 157 | //! ``` 158 | //! #[cfg_attr(test, mockable)] 159 | //! fn my_function_1(_: u32) { 160 | //! return 161 | //! } 162 | //! 163 | //! #[test] 164 | //! fn my_function_1_test() { 165 | //! my_function_1.mock_safe(|x| { 166 | //! assert_eq!(2, x); 167 | //! MockResult::Return(()) 168 | //! }); 169 | //! 170 | //! my_function_1(2); // Passes 171 | //! my_function_1(3); // Panics 172 | //! } 173 | //! ``` 174 | //! If the closure returns `MockResult::Return`, the mocked function does not run. 175 | //! It immediately returns with a value, which is passed inside `MockResult::Return`: 176 | //! 177 | //! ``` 178 | //! #[cfg_attr(test, mockable)] 179 | //! fn my_function_2() -> u32 { 180 | //! unreachable!() 181 | //! } 182 | //! 183 | //! #[test] 184 | //! fn my_function_2_test() { 185 | //! my_function_2.mock_safe(|| MockResult::Return(3)); 186 | //! 187 | //! assert_eq!(3, my_function_2()); 188 | //! } 189 | //! ``` 190 | //! If the closure returns `MockResult::Continue`, the mocked function runs normally, but with changed arguments. 191 | //! The new arguments are returned from closure in tuple inside `MockResult::Continue`: 192 | //! 193 | //! ``` 194 | //! #[cfg_attr(test, mockable)] 195 | //! fn my_function_3(x: u32, y: u32) -> u32 { 196 | //! x + y 197 | //! } 198 | //! 199 | //! #[test] 200 | //! fn my_function_3_test() { 201 | //! my_function_3.mock_safe(|x, y| MockResult::Continue((x, y + 1))); 202 | //! 203 | //! assert_eq!(3, my_function_3(1, 1)); 204 | //! } 205 | //! ``` 206 | //! 207 | //! ## Mocking generics 208 | //! When mocking generic functions, all its generics must be defined and only this variant will be affected: 209 | //! 210 | //! ``` 211 | //! #[cfg_attr(test, mockable)] 212 | //! fn generic_fn(t: T) -> String { 213 | //! t.to_string() 214 | //! } 215 | //! 216 | //! #[test] 217 | //! fn generic_fn_test() { 218 | //! generic_fn::.mock_safe(|_| MockResult::Return("mocked".to_string())); 219 | //! 220 | //! assert_eq!("1", generic_fn(1i32)); 221 | //! assert_eq!("mocked", generic_fn(1u32)); 222 | //! } 223 | //! ``` 224 | //! The only exception are lifetimes, they are ignored: 225 | //! 226 | //! ``` 227 | //! #[cfg_attr(test, mockable)] 228 | //! fn lifetime_generic_fn<'a>(string: &'a String) -> &'a str { 229 | //! string.as_ref() 230 | //! } 231 | //! 232 | //! #[test] 233 | //! fn lifetime_generic_fn_test() { 234 | //! lifetime_generic_fn.mock_safe(|_| MockResult::Return("mocked")); 235 | //! 236 | //! assert_eq!("mocked", lifetime_generic_fn(&"not mocked".to_string())); 237 | //! } 238 | //! ``` 239 | //! Same rules apply to methods and structures: 240 | //! 241 | //! ``` 242 | //! struct GenericStruct<'a, T: Display + 'a>(&'a T); 243 | //! 244 | //! #[cfg_attr(test, mockable)] 245 | //! impl<'a, T: Display + 'a> GenericStruct<'a, T> { 246 | //! fn to_string(&self) -> String { 247 | //! self.0.to_string() 248 | //! } 249 | //! } 250 | //! 251 | //! static VALUE: u32 = 1; 252 | //! 253 | //! #[test] 254 | //! fn lifetime_generic_fn_test() { 255 | //! GenericStruct::::to_string.mock_safe(|_| MockResult::Return("mocked".to_string())); 256 | //! 257 | //! assert_eq!("mocked", GenericStruct(&VALUE).to_string()); 258 | //! assert_eq!("mocked", GenericStruct(&2u32).to_string()); 259 | //! assert_eq!("2", GenericStruct(&2i32).to_string()); 260 | //! } 261 | //! ``` 262 | //! 263 | //! ## Mocking async 264 | //! Mocking async functions is almost exactly the same as non-async: 265 | //! 266 | //! ``` 267 | //! #[cfg_attr(test, mockable)] 268 | //! async fn sleep(ms: u64) { 269 | //! tokio::time::delay_for(std::time::Duration::from_millis(ms)).await; 270 | //! } 271 | //! 272 | //! #[tokio::test] 273 | //! async fn sleep_test() { 274 | //! sleep.mock_safe(|_| MockResult::Return(Box::pin(async move { () }))); 275 | //! 276 | //! sleep(10000).await; 277 | //! } 278 | //! ``` 279 | //! 280 | //! # Mocking tricks 281 | //! ## Returning reference to value created inside mock 282 | //! 283 | //! ``` 284 | //! #[mockable] 285 | //! fn my_fn(my_string: &String) -> &String { 286 | //! my_string 287 | //! } 288 | //! 289 | //! #[test] 290 | //! fn my_fn_test() { 291 | //! my_fn.mock_safe(|_| MockResult::Return(Box::leak(Box::new("mocked".to_string())))); 292 | //! 293 | //! assert_eq!("mocked", my_fn(&"not mocked 1")); 294 | //! assert_eq!("mocked", my_fn(&"not mocked 2")); 295 | //! } 296 | //! ``` 297 | //! The trick is to store referenced value in a `Box::new` and then prevent its deallocation with `Box::leak`. 298 | //! This makes structure live forever and returns a `&'static mut` reference to it. The value is not freed until 299 | //! process termination, so it's viable solution only for use in tests and only if structure doesn't block a lot of 300 | //! resources like huge amounts of memory, open file handlers, sockets, etc. 301 | //! 302 | //! ## Returning value created outside of mock 303 | //! 304 | //! ``` 305 | //! #[mockable] 306 | //! fn my_fn() -> String { 307 | //! "not mocked".to_string() 308 | //! } 309 | //! 310 | //! #[test] 311 | //! fn my_fn_test() { 312 | //! mock = Some("mocked".to_string()); 313 | //! my_fn.mock_safe(move || MockResult::Return(mock.unwrap())); 314 | //! 315 | //! assert_eq!("mocked", my_fn()); 316 | //! // assert_eq!("mocked", my_fn()); // WILL PANIC! 317 | //! } 318 | //! ``` 319 | //! This makes function return predefined value on first call and panic on second one. It could return 320 | //! `MockResult::Continue` instead of panicking to mock only first call. 321 | //! 322 | //! Returned values can be stored in a vector if mock should return different value on different calls: 323 | //! 324 | //! ```//! 325 | //! #[test] 326 | //! fn my_fn_test() { 327 | //! mut mock = vec!["mocked 1".to_string(), "mocked 2".to_string()]; 328 | //! my_fn.mock_safe(move || MockResult::Return(mock.remove(0))); 329 | //! 330 | //! assert_eq!("mocked 1", my_fn()); 331 | //! assert_eq!("mocked 2", my_fn()); 332 | //! // assert_eq!("mocked 3", my_fn()); // WILL PANIC! 333 | //! } 334 | //! ``` 335 | //! The vector can store `MockResult`s for more complex mocking. 336 | #![doc( 337 | html_logo_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png", 338 | html_favicon_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png" 339 | )] 340 | 341 | extern crate mocktopus_macros; 342 | 343 | /// For use in testing code: mocking tools 344 | pub mod mocking; 345 | 346 | /// For use in testing code: helper tools for writing tests using mocking 347 | pub mod mocking_utils; 348 | 349 | /// For use in tested code: tools making items mockable 350 | pub mod macros { 351 | pub use mocktopus_macros::*; 352 | } 353 | 354 | mod mock_store; 355 | -------------------------------------------------------------------------------- /src/mock_store.rs: -------------------------------------------------------------------------------- 1 | use crate::mocking::MockResult; 2 | use std::{any::TypeId, marker::Tuple}; 3 | use std::cell::RefCell; 4 | use std::collections::HashMap; 5 | use std::mem::transmute; 6 | use std::rc::Rc; 7 | 8 | pub struct MockStore { 9 | layers: RefCell>, 10 | } 11 | 12 | impl MockStore { 13 | pub fn clear(&self) { 14 | for layer in self.layers.borrow_mut().iter_mut() { 15 | layer.clear() 16 | } 17 | } 18 | 19 | pub fn clear_id(&self, id: TypeId) { 20 | for layer in self.layers.borrow_mut().iter_mut() { 21 | layer.clear_id(id) 22 | } 23 | } 24 | 25 | /// Layer will be in use as long as MockLayerGuard is alive 26 | /// MockLayerGuards must always be dropped and always in reverse order of their creation 27 | pub unsafe fn add_layer(&self, layer: MockLayer) { 28 | self.layers.borrow_mut().push(layer) 29 | } 30 | 31 | pub unsafe fn remove_layer(&self) { 32 | self.layers.borrow_mut().pop(); 33 | } 34 | 35 | pub unsafe fn add_to_thread_layer( 36 | &self, 37 | id: TypeId, 38 | mock: Box> + 'static>, 39 | ) { 40 | self.layers 41 | .borrow_mut() 42 | .first_mut() 43 | .expect("Thread mock level missing") 44 | .add(id, mock); 45 | } 46 | 47 | pub unsafe fn call(&self, id: TypeId, mut input: I) -> MockResult { 48 | // Do not hold RefCell borrow while calling mock, it can try to modify mocks 49 | let layer_count = self.layers.borrow().len(); 50 | for layer_idx in (0..layer_count).rev() { 51 | let mock_opt = self 52 | .layers 53 | .borrow() 54 | .get(layer_idx) 55 | .expect("Mock layer removed while iterating") 56 | .get(id); 57 | if let Some(mock) = mock_opt { 58 | match mock.call(input) { 59 | MockLayerResult::Handled(result) => return result, 60 | MockLayerResult::Unhandled(new_input) => input = new_input, 61 | } 62 | } 63 | } 64 | MockResult::Continue(input) 65 | } 66 | } 67 | 68 | //TODO tests 69 | // clear 70 | // clear id 71 | // add and remove layer 72 | // inside mock closure 73 | 74 | impl Default for MockStore { 75 | fn default() -> Self { 76 | MockStore { 77 | layers: RefCell::new(vec![MockLayer::default()]), 78 | } 79 | } 80 | } 81 | 82 | #[derive(Default)] 83 | pub struct MockLayer { 84 | mocks: HashMap, 85 | } 86 | 87 | impl MockLayer { 88 | fn clear(&mut self) { 89 | self.mocks.clear() 90 | } 91 | 92 | fn clear_id(&mut self, id: TypeId) { 93 | self.mocks.remove(&id); 94 | } 95 | 96 | pub unsafe fn add( 97 | &mut self, 98 | id: TypeId, 99 | mock: Box> + 'static>, 100 | ) { 101 | let stored = StoredMock::new(mock).erase(); 102 | self.mocks.insert(id, stored); 103 | } 104 | 105 | unsafe fn get(&self, id: TypeId) -> Option { 106 | self.mocks.get(&id).cloned() 107 | } 108 | } 109 | 110 | pub enum MockLayerResult { 111 | Handled(MockResult), 112 | Unhandled(I), 113 | } 114 | 115 | #[derive(Clone)] 116 | struct ErasedStoredMock { 117 | mock: StoredMock<(), ()>, 118 | } 119 | 120 | impl ErasedStoredMock { 121 | unsafe fn call(self, input: I) -> MockLayerResult { 122 | let unerased: StoredMock = transmute(self.mock); 123 | unerased.call(input) 124 | } 125 | } 126 | 127 | /// Guarantees that while mock is running it's not overwritten, destroyed, or called again 128 | #[derive(Clone)] 129 | struct StoredMock { 130 | mock: Rc>>>>, 131 | } 132 | 133 | impl StoredMock { 134 | fn new(mock: Box> + 'static>) -> Self { 135 | StoredMock { 136 | mock: Rc::new(RefCell::new(mock)), 137 | } 138 | } 139 | 140 | fn call(&self, input: I) -> MockLayerResult { 141 | match self.mock.try_borrow_mut() { 142 | Ok(mut mock) => MockLayerResult::Handled(mock.call_mut(input)), 143 | Err(_) => MockLayerResult::Unhandled(input), 144 | } 145 | } 146 | 147 | fn erase(self) -> ErasedStoredMock { 148 | unsafe { 149 | ErasedStoredMock { 150 | mock: transmute(self), 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/mocking.rs: -------------------------------------------------------------------------------- 1 | use crate::mock_store::{MockLayer, MockStore}; 2 | use std::{any::{Any, TypeId}, marker::Tuple}; 3 | use std::marker::PhantomData; 4 | use std::mem::transmute; 5 | 6 | /// Trait for setting up mocks 7 | /// 8 | /// The trait is implemented for all functions, so its methods can be called on any function. 9 | /// 10 | /// Note: methods have any effect only if called on functions [annotated as mockable](https://docs.rs/mocktopus_macros). 11 | pub trait Mockable { 12 | /// Core function for setting up mocks 13 | /// 14 | /// Always consider using [mock_safe](#tymethod.mock_safe) or [MockContext](struct.MockContext.html). 15 | /// 16 | /// The passed closure is called whenever the mocked function is called. Depending on variant of returned 17 | /// [MockResult](enum.MockResult.html) the mocked function continues to run or returns immediately. 18 | /// In case of continuation the function arguments can be modified or replaced. 19 | /// 20 | /// The mock closure is saved in a 21 | /// [thread local static storage](https://doc.rust-lang.org/std/macro.thread_local.html), 22 | /// so it has effect only in thread, where it was set. 23 | /// Each Rust test is executed in separate thread, so mocks do not leak between them. 24 | /// # Safety 25 | /// It is up to the user to make sure, that the closure is valid long enough to serve all calls to mocked function. 26 | /// If the mock closure uses any non-static values or references, it will silently become invalid at some point of 27 | /// host thread lifetime. 28 | /// 29 | /// ``` 30 | /// #[mockable] 31 | /// fn get_string(context: &Context) -> &String { 32 | /// context.get_string() 33 | /// } 34 | /// 35 | /// #[test] 36 | /// fn get_string_test() { 37 | /// let mocked = "mocked".to_string(); 38 | /// unsafe { 39 | /// get_string.mock_raw(|_| MockResult::Return(&mocked)); 40 | /// } 41 | /// 42 | /// assert_eq!("mocked", get_string(&Context::default())); 43 | /// } 44 | /// ``` 45 | unsafe fn mock_raw>>(&self, mock: M); 46 | 47 | /// A safe variant of [mock_raw](#tymethod.mock_raw) for static closures 48 | /// 49 | /// The safety is guaranteed by forcing passed closure to be static. 50 | /// This eliminates the problem of using non-static values, which may not live long enough. 51 | /// 52 | /// ``` 53 | /// #[mockable] 54 | /// fn get_string() -> String { 55 | /// "not mocked".to_string() 56 | /// } 57 | /// 58 | /// #[test] 59 | /// fn get_string_test() { 60 | /// get_string.mock_safe(|| MockResult::Return("mocked".to_string())); 61 | /// 62 | /// assert_eq!("mocked", get_string()); 63 | /// } 64 | /// ``` 65 | fn mock_safe> + 'static>(&self, mock: M); 66 | 67 | /// Stop mocking this function. 68 | /// 69 | /// All future invocations will be forwarded to the real implementation. 70 | fn clear_mock(&self); 71 | 72 | #[doc(hidden)] 73 | /// Called before every execution of a mockable function. Checks if mock is set and if it is, calls it. 74 | fn call_mock(&self, input: T) -> MockResult; 75 | 76 | #[doc(hidden)] 77 | /// Returns a unique ID of the function, which is used to set and get its mock. 78 | unsafe fn get_mock_id(&self) -> TypeId; 79 | } 80 | 81 | /// Controls mocked function behavior when returned from [mock closure](trait.Mockable.html) 82 | pub enum MockResult { 83 | /// Function runs normally as if it was called with given arguments. 84 | /// The arguments are passed inside enum variant as a tuple. 85 | Continue(T), 86 | 87 | /// Function returns immediately with a given value. The returned value is passed inside enum variant. 88 | Return(O), 89 | } 90 | 91 | thread_local! { 92 | static MOCK_STORE: MockStore = MockStore::default() 93 | } 94 | 95 | /// Clear all mocks in the ThreadLocal; only necessary if tests share threads 96 | pub fn clear_mocks() { 97 | MOCK_STORE.with(|mock_store| mock_store.clear()) 98 | } 99 | 100 | impl> Mockable for F { 101 | unsafe fn mock_raw>>(&self, mock: M) { 102 | let id = self.get_mock_id(); 103 | let boxed = Box::new(mock) as Box>; 104 | let static_boxed: Box> + 'static> = transmute(boxed); 105 | MOCK_STORE.with(|mock_store| mock_store.add_to_thread_layer(id, static_boxed)) 106 | } 107 | 108 | fn mock_safe> + 'static>(&self, mock: M) { 109 | unsafe { self.mock_raw(mock) } 110 | } 111 | 112 | fn clear_mock(&self) { 113 | let id = unsafe { self.get_mock_id() }; 114 | MOCK_STORE.with(|mock_store| mock_store.clear_id(id)) 115 | } 116 | 117 | fn call_mock(&self, input: T) -> MockResult { 118 | unsafe { 119 | let id = self.get_mock_id(); 120 | MOCK_STORE.with(|mock_store| mock_store.call(id, input)) 121 | } 122 | } 123 | 124 | unsafe fn get_mock_id(&self) -> TypeId { 125 | (|| ()).type_id() 126 | } 127 | } 128 | 129 | /// `MockContext` allows for safe capture of local variables. 130 | /// 131 | /// It does this by forcing only mocking the actual function while in the body 132 | /// of [run](#tymethod.run). 133 | /// 134 | /// # Examples 135 | /// 136 | /// Simple function replacement: 137 | /// 138 | /// ``` 139 | /// use mocktopus::macros::mockable; 140 | /// use mocktopus::mocking::{MockContext, MockResult}; 141 | /// 142 | /// #[mockable] 143 | /// fn f() -> i32 { 144 | /// 0 145 | /// } 146 | /// 147 | /// MockContext::new() 148 | /// .mock_safe(f, || MockResult::Return(1)) 149 | /// .run(|| { 150 | /// assert_eq!(f(), 1); 151 | /// }); 152 | /// ``` 153 | /// 154 | /// Using local variables: 155 | /// 156 | /// ``` 157 | /// use mocktopus::macros::mockable; 158 | /// use mocktopus::mocking::{MockContext, MockResult}; 159 | /// 160 | /// #[mockable] 161 | /// fn as_str(s: &String) -> &str { 162 | /// &s 163 | /// } 164 | /// 165 | /// let mut count = 0; 166 | /// MockContext::new() 167 | /// .mock_safe(as_str, |s| { count += 1; MockResult::Return(&s) }) 168 | /// .run(|| { 169 | /// assert_eq!(as_str(&"abc".to_string()), "abc"); 170 | /// }); 171 | /// assert_eq!(count, 1); 172 | /// ``` 173 | #[derive(Default)] 174 | pub struct MockContext<'a> { 175 | mock_layer: MockLayer, 176 | phantom_lifetime: PhantomData<&'a ()>, 177 | } 178 | 179 | impl<'a> MockContext<'a> { 180 | /// Create a new MockContext object. 181 | pub fn new() -> Self { 182 | Self::default() 183 | } 184 | 185 | /// Set up a function to be mocked. 186 | /// 187 | /// This function doesn't actually mock the function. It registers it as a 188 | /// function that will be mocked when [`run`](#method.run) is called. 189 | pub fn mock_safe(self, mockable: F, mock: M) -> Self 190 | where 191 | F: Mockable, 192 | M: FnMut> + 'a, 193 | { 194 | unsafe { self.mock_raw(mockable, mock) } 195 | } 196 | 197 | /// Set up a function to be mocked. 198 | /// 199 | /// This is an unsafe version of [`mock_safe`](#method.mock_safe), 200 | /// without lifetime constraint on mock 201 | pub unsafe fn mock_raw(mut self, mockable: F, mock: M) -> Self 202 | where 203 | F: Mockable, 204 | M: FnMut>, 205 | { 206 | let mock_box = Box::new(mock) as Box>; 207 | let mock_box_static: Box> + 'static> = 208 | std::mem::transmute(mock_box); 209 | self.mock_layer.add(mockable.get_mock_id(), mock_box_static); 210 | self 211 | } 212 | 213 | /// Run the function while mocking all the functions. 214 | /// 215 | /// This function will mock all functions registered for mocking, run the 216 | /// function passed in, then deregister those functions. It does this in a 217 | /// panic-safe way. Note that functions are only mocked in the current 218 | /// thread and other threads may invoke the real implementations. 219 | /// 220 | /// Register a function for mocking with [`mock_safe`](#method.mock_safe). 221 | pub fn run T>(self, f: F) -> T { 222 | MOCK_STORE.with(|mock_store| unsafe { mock_store.add_layer(self.mock_layer) }); 223 | let _mock_level_guard = MockLayerGuard; 224 | f() 225 | } 226 | } 227 | 228 | struct MockLayerGuard; 229 | 230 | impl<'a> Drop for MockLayerGuard { 231 | fn drop(&mut self) { 232 | MOCK_STORE.with(|mock_store| unsafe { mock_store.remove_layer() }); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /src/mocking_utils.rs: -------------------------------------------------------------------------------- 1 | /// Converts non-mutable reference to a mutable one 2 | /// 3 | /// Allows creating multiple mutable references to a single item breaking Rust's safety policy. 4 | /// # Safety 5 | /// Use with extreme caution, may cause all sorts of mutability related undefined behaviors! 6 | /// 7 | /// One safe use case is when mocking function, which gets called only once during whole test execution, for example: 8 | /// 9 | /// ``` 10 | /// #[mockable] 11 | /// fn get_string(context: &mut Context) -> &mut String { 12 | /// context.get_mut_string() 13 | /// } 14 | /// 15 | /// #[test] 16 | /// fn get_string_test() { 17 | /// let mocked = "mocked".to_string(); 18 | /// unsafe { 19 | /// // MockResult::Return(&mut string) would fail 20 | /// get_string.mock_raw(|_| MockResult::Return(as_mut(&mocked))); 21 | /// } 22 | /// 23 | /// assert_eq!("mocked", get_string(&mut Context::default())); 24 | /// } 25 | /// ``` 26 | pub unsafe fn as_mut(t_ref: &T) -> &mut T { 27 | &mut *(t_ref as *const T as *mut T) 28 | } 29 | -------------------------------------------------------------------------------- /tests/injecting_no_std.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | extern crate mocktopus; 4 | 5 | use mocktopus::macros::*; 6 | use mocktopus::mocking::*; 7 | 8 | mod injector_injects_fns_when_crate_is_no_std_but_std_is_available { 9 | use super::*; 10 | 11 | #[mockable] 12 | fn function(arg: u8) -> u8 { 13 | arg * 2 14 | } 15 | 16 | #[test] 17 | fn when_not_mocked_then_runs_normally() { 18 | assert_eq!(4, function(2)); 19 | } 20 | 21 | #[test] 22 | fn when_mocked_then_runs_mock() { 23 | function.mock_safe(|_| MockResult::Return(3)); 24 | 25 | assert_eq!(3, function(2)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/mocking_fns/mod.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | mod when_fn_generic; 4 | mod when_fn_generic_async; 5 | mod when_fn_regular; 6 | mod when_fn_regular_async; 7 | -------------------------------------------------------------------------------- /tests/mocking_fns/when_fn_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | fn function(arg: bool, fn_generic: T) -> String { 5 | format!("{} {}", arg, fn_generic) 6 | } 7 | 8 | #[test] 9 | fn and_not_mocked_then_runs_normally() { 10 | assert_eq!("true 2.5", function(true, 2.5f32)); 11 | assert_eq!("true abc", function(true, "abc")); 12 | } 13 | 14 | #[test] 15 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 16 | unsafe { 17 | function::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 18 | } 19 | 20 | assert_eq!("false 3.5", function(true, 2.5f32)); 21 | assert_eq!("true abc", function(true, "abc")); 22 | } 23 | 24 | #[test] 25 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 26 | unsafe { 27 | function::.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 28 | } 29 | 30 | assert_eq!("mocked true 2.5", function(true, 2.5f32)); 31 | assert_eq!("true abc", function(true, "abc")); 32 | } 33 | -------------------------------------------------------------------------------- /tests/mocking_fns/when_fn_generic_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | async fn function(arg: bool, fn_generic: T) -> String { 5 | format!("{} {}", arg, fn_generic) 6 | } 7 | 8 | #[tokio::test] 9 | async fn and_not_mocked_then_runs_normally() { 10 | assert_eq!("true 2.5", function(true, 2.5f32).await); 11 | assert_eq!("true abc", function(true, "abc").await); 12 | } 13 | 14 | #[tokio::test] 15 | async fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 16 | unsafe { 17 | function::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 18 | } 19 | 20 | assert_eq!("false 3.5", function(true, 2.5f32).await); 21 | assert_eq!("true abc", function(true, "abc").await); 22 | } 23 | 24 | #[tokio::test] 25 | async fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 26 | unsafe { 27 | function::.mock_raw(|a, b| { 28 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a, b) })) 29 | }); 30 | } 31 | 32 | assert_eq!("mocked true 2.5", function(true, 2.5f32).await); 33 | assert_eq!("true abc", function(true, "abc").await); 34 | } 35 | -------------------------------------------------------------------------------- /tests/mocking_fns/when_fn_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | fn function(arg: bool) -> String { 5 | format!("{}", arg) 6 | } 7 | 8 | #[test] 9 | fn and_not_mocked_then_runs_normally() { 10 | assert_eq!("true", function(true)); 11 | } 12 | 13 | #[test] 14 | fn and_continue_mocked_then_runs_with_modified_args() { 15 | unsafe { 16 | function.mock_raw(|a| MockResult::Continue((!a,))); 17 | } 18 | 19 | assert_eq!("false", function(true)); 20 | } 21 | 22 | #[test] 23 | fn and_return_mocked_then_returns_mocking_result() { 24 | unsafe { 25 | function.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 26 | } 27 | 28 | assert_eq!("mocked true", function(true)); 29 | } 30 | -------------------------------------------------------------------------------- /tests/mocking_fns/when_fn_regular_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | async fn function(arg: bool) -> String { 5 | format!("{}", arg) 6 | } 7 | 8 | #[tokio::test] 9 | async fn and_not_mocked_then_runs_normally() { 10 | assert_eq!("true", function(true).await); 11 | } 12 | 13 | #[tokio::test] 14 | async fn and_continue_mocked_then_runs_with_modified_args() { 15 | unsafe { 16 | function.mock_raw(|a| MockResult::Continue((!a,))); 17 | } 18 | 19 | assert_eq!("false", function(true).await); 20 | } 21 | 22 | #[tokio::test] 23 | async fn and_return_mocked_then_returns_mocking_result() { 24 | unsafe { 25 | function.mock_raw(|a| MockResult::Return(Box::pin(async move { format!("mocked {}", a) }))); 26 | } 27 | 28 | assert_eq!("mocked true", function(true).await); 29 | } 30 | -------------------------------------------------------------------------------- /tests/mocking_methods/mod.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | mod when_struct_generic_method_generic; 4 | mod when_struct_generic_method_regular; 5 | mod when_struct_regular_method_generic; 6 | mod when_struct_regular_method_regular; 7 | -------------------------------------------------------------------------------- /tests/mocking_methods/when_struct_generic_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(T); 4 | 5 | #[mockable] 6 | impl Struct { 7 | fn static_method(arg: bool, method_generic: U) -> String { 8 | format!("{} {}", arg, method_generic) 9 | } 10 | 11 | fn ref_method(&self, arg: bool, method_generic: U) -> String { 12 | format!("{} {} {}", self.0, arg, method_generic) 13 | } 14 | 15 | fn ref_mut_method(&mut self, arg: bool, method_generic: U) -> String { 16 | self.0 = T::default(); 17 | format!("{} {} {}", self.0, arg, method_generic) 18 | } 19 | 20 | fn val_method(self, arg: bool, method_generic: U) -> String { 21 | format!("{} {} {}", self.0, arg, method_generic) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[test] 29 | fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true 2.5", Struct::::static_method(true, 2.5f32)); 31 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 32 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 33 | } 34 | 35 | #[test] 36 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 37 | unsafe { 38 | Struct::::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 39 | } 40 | 41 | assert_eq!("false 3.5", Struct::::static_method(true, 2.5f32)); 42 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 43 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 44 | } 45 | 46 | #[test] 47 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 48 | unsafe { 49 | Struct::::static_method:: 50 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 51 | } 52 | 53 | assert_eq!("mocked true 2.5", Struct::::static_method(true, 2.5f32)); 54 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 55 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 56 | } 57 | } 58 | 59 | mod and_method_is_ref_method { 60 | use super::*; 61 | 62 | #[test] 63 | fn and_not_mocked_then_runs_normally() { 64 | assert_eq!("2 true 1.5", Struct(2u8).ref_method(true, 1.5f32)); 65 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 66 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 67 | } 68 | 69 | #[test] 70 | fn and_continue_mocked_then_runs_with_modified_args() { 71 | let struct_2 = Struct(2u8); 72 | let struct_3 = Struct(3u8); 73 | unsafe { 74 | Struct::::ref_method:: 75 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 76 | } 77 | 78 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32)); 79 | assert_eq!(2, struct_2.0); 80 | assert_eq!(3, struct_3.0); 81 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 82 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 83 | } 84 | 85 | #[test] 86 | fn and_return_mocked_then_returns_mocking_result() { 87 | let struct_2 = Struct(2u8); 88 | unsafe { 89 | Struct::::ref_method:: 90 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 91 | } 92 | 93 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32)); 94 | assert_eq!(2, struct_2.0); 95 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 96 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 97 | } 98 | } 99 | 100 | mod and_method_is_ref_mut_method { 101 | use super::*; 102 | 103 | #[test] 104 | fn and_not_mocked_then_runs_normally() { 105 | let mut struct_2 = Struct(2u8); 106 | let mut struct_4 = Struct(4u8); 107 | let mut struct_str = Struct("abc"); 108 | 109 | assert_eq!("0 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 110 | assert_eq!(0, struct_2.0); 111 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 112 | assert_eq!(0, struct_4.0); 113 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 114 | assert_eq!("", struct_str.0); 115 | } 116 | 117 | #[test] 118 | fn and_continue_mocked_then_runs_with_modified_args() { 119 | let mut struct_2 = Struct(2u8); 120 | let struct_3 = Struct(3u8); 121 | let mut struct_4 = Struct(4u8); 122 | let mut struct_str = Struct("abc"); 123 | unsafe { 124 | Struct::::ref_mut_method:: 125 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 126 | } 127 | 128 | assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); 129 | assert_eq!(2, struct_2.0); 130 | assert_eq!(0, struct_3.0); 131 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 132 | assert_eq!(0, struct_4.0); 133 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 134 | assert_eq!("", struct_str.0); 135 | } 136 | 137 | #[test] 138 | fn and_return_mocked_then_returns_mocking_result() { 139 | let mut struct_2 = Struct(2u8); 140 | let mut struct_4 = Struct(4u8); 141 | let mut struct_str = Struct("abc"); 142 | unsafe { 143 | Struct::::ref_mut_method:: 144 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 145 | } 146 | 147 | assert_eq!("mocked 2 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 148 | assert_eq!(2, struct_2.0); 149 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 150 | assert_eq!(0, struct_4.0); 151 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 152 | assert_eq!("", struct_str.0); 153 | } 154 | } 155 | 156 | mod and_method_is_val_method { 157 | use super::*; 158 | 159 | #[test] 160 | fn and_not_mocked_then_runs_normally() { 161 | assert_eq!("2 true 1.5", Struct(2u8).val_method(true, 1.5f32)); 162 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 163 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 164 | } 165 | 166 | #[test] 167 | fn and_continue_mocked_then_runs_with_modified_args() { 168 | unsafe { 169 | Struct::::val_method:: 170 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3u8), !b, c + 1.))); 171 | } 172 | 173 | assert_eq!("3 false 2.5", Struct(2u8).val_method(true, 1.5f32)); 174 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 175 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 176 | } 177 | 178 | #[test] 179 | fn and_return_mocked_then_returns_mocking_result() { 180 | unsafe { 181 | Struct::::val_method:: 182 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 183 | } 184 | 185 | assert_eq!("mocked 2 true 1.5", Struct(2u8).val_method(true, 1.5f32)); 186 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 187 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /tests/mocking_methods/when_struct_generic_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(T); 4 | 5 | #[mockable] 6 | impl Struct { 7 | fn static_method(arg: bool) -> String { 8 | format!("{}", arg) 9 | } 10 | 11 | fn ref_method(&self, arg: bool) -> String { 12 | format!("{} {}", self.0, arg) 13 | } 14 | 15 | fn ref_mut_method(&mut self, arg: bool) -> String { 16 | self.0 = T::default(); 17 | format!("{} {}", self.0, arg) 18 | } 19 | 20 | fn val_method(self, arg: bool) -> String { 21 | format!("{} {}", self.0, arg) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[test] 29 | fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true", Struct::::static_method(true)); 31 | assert_eq!("true", Struct::<&str>::static_method(true)); 32 | } 33 | 34 | #[test] 35 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 36 | unsafe { 37 | Struct::::static_method.mock_raw(|a| MockResult::Continue((!a,))); 38 | } 39 | 40 | assert_eq!("false", Struct::::static_method(true)); 41 | assert_eq!("true", Struct::<&str>::static_method(true)); 42 | } 43 | 44 | #[test] 45 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 46 | unsafe { 47 | Struct::::static_method.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 48 | } 49 | 50 | assert_eq!("mocked true", Struct::::static_method(true)); 51 | assert_eq!("true", Struct::<&str>::static_method(true)); 52 | } 53 | } 54 | 55 | mod and_method_is_ref_method { 56 | use super::*; 57 | 58 | #[test] 59 | fn and_not_mocked_then_runs_normally() { 60 | assert_eq!("2 true", Struct(2u8).ref_method(true)); 61 | assert_eq!("abc true", Struct("abc").ref_method(true)); 62 | } 63 | 64 | #[test] 65 | fn and_continue_mocked_then_runs_with_modified_args() { 66 | let struct_2 = Struct(2u8); 67 | let struct_3 = Struct(3u8); 68 | unsafe { 69 | Struct::::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 70 | } 71 | 72 | assert_eq!("3 false", struct_2.ref_method(true)); 73 | assert_eq!(2, struct_2.0); 74 | assert_eq!(3, struct_3.0); 75 | assert_eq!("abc true", Struct("abc").ref_method(true)); 76 | } 77 | 78 | #[test] 79 | fn and_return_mocked_then_returns_mocking_result() { 80 | let struct_2 = Struct(2u8); 81 | unsafe { 82 | Struct::::ref_method 83 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 84 | } 85 | 86 | assert_eq!("mocked 2 true", struct_2.ref_method(true)); 87 | assert_eq!(2, struct_2.0); 88 | assert_eq!("abc true", Struct("abc").ref_method(true)); 89 | } 90 | } 91 | 92 | mod and_method_is_ref_mut_method { 93 | use super::*; 94 | 95 | #[test] 96 | fn and_not_mocked_then_runs_normally() { 97 | let mut struct_2 = Struct(2u8); 98 | let mut struct_str = Struct("str"); 99 | 100 | assert_eq!("0 true", struct_2.ref_mut_method(true)); 101 | assert_eq!(0, struct_2.0); 102 | assert_eq!(" true", struct_str.ref_mut_method(true)); 103 | assert_eq!("", struct_str.0); 104 | } 105 | 106 | #[test] 107 | fn and_continue_mocked_then_runs_with_modified_args() { 108 | let mut struct_2 = Struct(2u8); 109 | let struct_3 = Struct(3u8); 110 | let mut struct_str = Struct("str"); 111 | unsafe { 112 | Struct::::ref_mut_method 113 | .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 114 | } 115 | 116 | assert_eq!("0 false", struct_2.ref_mut_method(true)); 117 | assert_eq!(2, struct_2.0); 118 | assert_eq!(0, struct_3.0); 119 | assert_eq!(" true", struct_str.ref_mut_method(true)); 120 | assert_eq!("", struct_str.0); 121 | } 122 | 123 | #[test] 124 | fn and_return_mocked_then_returns_mocking_result() { 125 | let mut struct_2 = Struct(2u8); 126 | let mut struct_str = Struct("str"); 127 | unsafe { 128 | Struct::::ref_mut_method 129 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 130 | } 131 | 132 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true)); 133 | assert_eq!(2, struct_2.0); 134 | assert_eq!(" true", struct_str.ref_mut_method(true)); 135 | assert_eq!("", struct_str.0); 136 | } 137 | } 138 | 139 | mod and_method_is_val_method { 140 | use super::*; 141 | 142 | #[test] 143 | fn and_not_mocked_then_runs_normally() { 144 | assert_eq!("2 true", Struct(2u8).val_method(true)); 145 | assert_eq!("abc true", Struct("abc").val_method(true)); 146 | } 147 | 148 | #[test] 149 | fn and_continue_mocked_then_runs_with_modified_args() { 150 | unsafe { 151 | Struct::::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3u8), !b))); 152 | } 153 | 154 | assert_eq!("3 false", Struct(2u8).val_method(true)); 155 | assert_eq!("abc true", Struct("abc").val_method(true)); 156 | } 157 | 158 | #[test] 159 | fn and_return_mocked_then_returns_mocking_result() { 160 | unsafe { 161 | Struct::::val_method 162 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 163 | } 164 | 165 | assert_eq!("mocked 2 true", Struct(2u8).val_method(true)); 166 | assert_eq!("abc true", Struct("abc").val_method(true)); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /tests/mocking_methods/when_struct_regular_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(u8); 4 | 5 | #[mockable] 6 | impl Struct { 7 | fn static_method(arg: bool, method_generic: T) -> String { 8 | format!("{} {}", arg, method_generic) 9 | } 10 | 11 | fn ref_method(&self, arg: bool, method_generic: T) -> String { 12 | format!("{} {} {}", self.0, arg, method_generic) 13 | } 14 | 15 | fn ref_mut_method(&mut self, arg: bool, method_generic: T) -> String { 16 | self.0 *= 2; 17 | format!("{} {} {}", self.0, arg, method_generic) 18 | } 19 | 20 | fn val_method(self, arg: bool, method_generic: T) -> String { 21 | format!("{} {} {}", self.0, arg, method_generic) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[test] 29 | fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true 1.5", Struct::static_method(true, 1.5f32)); 31 | assert_eq!("true abc", Struct::static_method(true, "abc")); 32 | } 33 | 34 | #[test] 35 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 36 | unsafe { 37 | Struct::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 38 | } 39 | 40 | assert_eq!("false 3.5", Struct::static_method(true, 2.5f32)); 41 | assert_eq!("true abc", Struct::static_method(true, "abc")); 42 | } 43 | 44 | #[test] 45 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 46 | unsafe { 47 | Struct::static_method:: 48 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 49 | } 50 | 51 | assert_eq!("mocked true 2.5", Struct::static_method(true, 2.5f32)); 52 | assert_eq!("true abc", Struct::static_method(true, "abc")); 53 | } 54 | } 55 | 56 | mod and_method_is_ref_method { 57 | use super::*; 58 | 59 | #[test] 60 | fn and_not_mocked_then_runs_normally() { 61 | assert_eq!("2 true 1.5", Struct(2).ref_method(true, 1.5f32)); 62 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 63 | } 64 | 65 | #[test] 66 | fn and_continue_mocked_then_runs_with_modified_args() { 67 | let struct_2 = Struct(2); 68 | let struct_3 = Struct(3); 69 | unsafe { 70 | Struct::ref_method:: 71 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 72 | } 73 | 74 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32)); 75 | assert_eq!(2, struct_2.0); 76 | assert_eq!(3, struct_3.0); 77 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 78 | } 79 | 80 | #[test] 81 | fn and_return_mocked_then_returns_mocking_result() { 82 | let struct_2 = Struct(2); 83 | unsafe { 84 | Struct::ref_method:: 85 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 86 | } 87 | 88 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32)); 89 | assert_eq!(2, struct_2.0); 90 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 91 | } 92 | } 93 | 94 | mod and_method_is_ref_mut_method { 95 | use super::*; 96 | 97 | #[test] 98 | fn and_not_mocked_then_runs_normally() { 99 | let mut struct_2 = Struct(2); 100 | let mut struct_4 = Struct(4); 101 | 102 | assert_eq!("4 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 103 | assert_eq!(4, struct_2.0); 104 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 105 | assert_eq!(8, struct_4.0); 106 | } 107 | 108 | #[test] 109 | fn and_continue_mocked_then_runs_with_modified_args() { 110 | let mut struct_2 = Struct(2); 111 | let struct_3 = Struct(3); 112 | let mut struct_4 = Struct(4); 113 | unsafe { 114 | Struct::ref_mut_method:: 115 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 116 | } 117 | 118 | assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); 119 | assert_eq!(2, struct_2.0); 120 | assert_eq!(6, struct_3.0); 121 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 122 | assert_eq!(8, struct_4.0); 123 | } 124 | 125 | #[test] 126 | fn and_return_mocked_then_returns_mocking_result() { 127 | let mut struct_2 = Struct(2); 128 | let mut struct_4 = Struct(4); 129 | unsafe { 130 | Struct::ref_mut_method:: 131 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 132 | } 133 | 134 | assert_eq!("mocked 2 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 135 | assert_eq!(2, struct_2.0); 136 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 137 | assert_eq!(8, struct_4.0); 138 | } 139 | } 140 | 141 | mod and_method_is_val_method { 142 | use super::*; 143 | 144 | #[test] 145 | fn and_not_mocked_then_runs_normally() { 146 | assert_eq!("2 true 1.5", Struct(2).val_method(true, 1.5f32)); 147 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 148 | } 149 | 150 | #[test] 151 | fn and_continue_mocked_then_runs_with_modified_args() { 152 | unsafe { 153 | Struct::val_method:: 154 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3), !b, c + 1.))); 155 | } 156 | 157 | assert_eq!("3 false 2.5", Struct(2).val_method(true, 1.5f32)); 158 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 159 | } 160 | 161 | #[test] 162 | fn and_return_mocked_then_returns_mocking_result() { 163 | unsafe { 164 | Struct::val_method:: 165 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 166 | } 167 | 168 | assert_eq!("mocked 2 true 1.5", Struct(2).val_method(true, 1.5f32)); 169 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /tests/mocking_methods/when_struct_regular_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(u8); 4 | 5 | #[mockable] 6 | impl Struct { 7 | fn static_method(arg: bool) -> String { 8 | format!("{}", arg) 9 | } 10 | 11 | fn ref_method(&self, arg: bool) -> String { 12 | format!("{} {}", self.0, arg) 13 | } 14 | 15 | fn ref_mut_method(&mut self, arg: bool) -> String { 16 | self.0 *= 2; 17 | format!("{} {}", self.0, arg) 18 | } 19 | 20 | fn val_method(self, arg: bool) -> String { 21 | format!("{} {}", self.0, arg) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[test] 29 | fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true", Struct::static_method(true)); 31 | } 32 | 33 | #[test] 34 | fn and_continue_mocked_then_runs_with_modified_args() { 35 | unsafe { 36 | Struct::static_method.mock_raw(|a| MockResult::Continue((!a,))); 37 | } 38 | 39 | assert_eq!("false", Struct::static_method(true)); 40 | } 41 | 42 | #[test] 43 | fn and_return_mocked_then_returns_mocking_result() { 44 | unsafe { 45 | Struct::static_method.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 46 | } 47 | 48 | assert_eq!("mocked true", Struct::static_method(true)); 49 | } 50 | } 51 | 52 | mod and_method_is_ref_method { 53 | use super::*; 54 | 55 | #[test] 56 | fn and_not_mocked_then_runs_normally() { 57 | assert_eq!("2 true", Struct(2).ref_method(true)); 58 | } 59 | 60 | #[test] 61 | fn and_continue_mocked_then_runs_with_modified_args() { 62 | let struct_2 = Struct(2); 63 | let struct_3 = Struct(3); 64 | unsafe { 65 | Struct::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 66 | } 67 | 68 | assert_eq!("3 false", struct_2.ref_method(true)); 69 | assert_eq!(2, struct_2.0); 70 | assert_eq!(3, struct_3.0); 71 | } 72 | 73 | #[test] 74 | fn and_return_mocked_then_returns_mocking_result() { 75 | let struct_2 = Struct(2); 76 | unsafe { 77 | Struct::ref_method.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 78 | } 79 | 80 | assert_eq!("mocked 2 true", struct_2.ref_method(true)); 81 | assert_eq!(2, struct_2.0); 82 | } 83 | } 84 | 85 | mod and_method_is_ref_mut_method { 86 | use super::*; 87 | 88 | #[test] 89 | fn and_not_mocked_then_runs_normally() { 90 | let mut struct_2 = Struct(2); 91 | 92 | assert_eq!("4 true", struct_2.ref_mut_method(true)); 93 | assert_eq!(4, struct_2.0); 94 | } 95 | 96 | #[test] 97 | fn and_continue_mocked_then_runs_with_modified_args() { 98 | let mut struct_2 = Struct(2); 99 | let struct_3 = Struct(3); 100 | unsafe { 101 | Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 102 | } 103 | 104 | assert_eq!("6 false", struct_2.ref_mut_method(true)); 105 | assert_eq!(2, struct_2.0); 106 | assert_eq!(6, struct_3.0); 107 | } 108 | 109 | #[test] 110 | fn and_return_mocked_then_returns_mocking_result() { 111 | let mut struct_2 = Struct(2); 112 | unsafe { 113 | Struct::ref_mut_method 114 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 115 | } 116 | 117 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true)); 118 | assert_eq!(2, struct_2.0); 119 | } 120 | } 121 | 122 | mod and_method_is_val_method { 123 | use super::*; 124 | 125 | #[test] 126 | fn and_not_mocked_then_runs_normally() { 127 | assert_eq!("2 true", Struct(2).val_method(true)); 128 | } 129 | 130 | #[test] 131 | fn and_continue_mocked_then_runs_with_modified_args() { 132 | unsafe { 133 | Struct::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3), !b))); 134 | } 135 | 136 | assert_eq!("3 false", Struct(2).val_method(true)); 137 | } 138 | 139 | #[test] 140 | fn and_return_mocked_then_returns_mocking_result() { 141 | unsafe { 142 | Struct::val_method.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 143 | } 144 | 145 | assert_eq!("mocked 2 true", Struct(2).val_method(true)); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /tests/mocking_methods_async/mod.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | mod when_struct_complex_method_regular_async; 4 | mod when_struct_generic_method_generic_async; 5 | mod when_struct_generic_method_regular_async; 6 | mod when_struct_regular_method_generic_async; 7 | mod when_struct_regular_method_regular_async; 8 | -------------------------------------------------------------------------------- /tests/mocking_methods_async/when_struct_complex_method_regular_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(u8); 4 | 5 | fn plus_one(value: u8) -> u8 { 6 | value + 1 7 | } 8 | 9 | #[mockable] 10 | impl Struct { 11 | async fn ref_method_with_binding(&self, arg: bool) -> String { 12 | let method_call = || async { self.0 }; 13 | 14 | format!("{} {}", method_call().await, arg) 15 | } 16 | 17 | async fn ref_method_with_ref(&self, arg: &bool) -> String { 18 | format!("{} {}", self.0, arg) 19 | } 20 | 21 | async fn ref_method_with_call(&self, arg: bool) -> String { 22 | format!("{} {}", plus_one(self.0), arg) 23 | } 24 | 25 | async fn assoc_method_with_ref(arg: &str) -> String { 26 | format!("Hello {}", arg) 27 | } 28 | 29 | async fn assoc_method_with_ref_and_lifetime<'a>(arg1: &'a str, arg2: &'a str) -> String { 30 | format!("{} {}", arg1, arg2) 31 | } 32 | } 33 | 34 | mod and_method_is_ref_method_with_binding { 35 | use super::*; 36 | 37 | #[tokio::test] 38 | async fn and_not_mocked_then_runs_normally() { 39 | assert_eq!("2 true", Struct(2).ref_method_with_binding(true).await); 40 | } 41 | 42 | #[tokio::test] 43 | async fn and_continue_mocked_then_runs_with_modified_args() { 44 | let struct_2 = Struct(2); 45 | let struct_3 = Struct(3); 46 | unsafe { 47 | Struct::ref_method_with_binding.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 48 | } 49 | 50 | assert_eq!("3 false", struct_2.ref_method_with_binding(true).await); 51 | assert_eq!(2, struct_2.0); 52 | assert_eq!(3, struct_3.0); 53 | } 54 | 55 | #[tokio::test] 56 | async fn and_return_mocked_then_returns_mocking_result() { 57 | let struct_2 = Struct(2); 58 | unsafe { 59 | Struct::ref_method_with_binding.mock_raw(|a, b| { 60 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 61 | }); 62 | } 63 | 64 | assert_eq!( 65 | "mocked 2 true", 66 | struct_2.ref_method_with_binding(true).await 67 | ); 68 | assert_eq!(2, struct_2.0); 69 | } 70 | } 71 | 72 | mod and_method_is_ref_method_with_ref { 73 | use super::*; 74 | 75 | #[tokio::test] 76 | async fn and_not_mocked_then_runs_normally() { 77 | assert_eq!("2 true", Struct(2).ref_method_with_ref(&true).await); 78 | } 79 | 80 | #[tokio::test] 81 | async fn and_return_mocked_then_returns_mocking_result() { 82 | let struct_2 = Struct(2); 83 | unsafe { 84 | Struct::ref_method_with_ref.mock_raw(|a, b| { 85 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 86 | }); 87 | } 88 | 89 | assert_eq!("mocked 2 true", struct_2.ref_method_with_ref(&true).await); 90 | assert_eq!(2, struct_2.0); 91 | } 92 | } 93 | 94 | mod and_method_is_ref_method_with_call { 95 | use super::*; 96 | 97 | #[tokio::test] 98 | async fn and_not_mocked_then_runs_normally() { 99 | assert_eq!("3 true", Struct(2).ref_method_with_call(true).await); 100 | } 101 | 102 | #[tokio::test] 103 | async fn and_continue_mocked_then_runs_with_modified_args() { 104 | let struct_2 = Struct(2); 105 | let struct_3 = Struct(3); 106 | unsafe { 107 | Struct::ref_method_with_call.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 108 | } 109 | 110 | assert_eq!("4 false", struct_2.ref_method_with_call(true).await); 111 | assert_eq!(2, struct_2.0); 112 | assert_eq!(3, struct_3.0); 113 | } 114 | 115 | #[tokio::test] 116 | async fn and_return_mocked_then_returns_mocking_result() { 117 | let struct_2 = Struct(2); 118 | unsafe { 119 | Struct::ref_method_with_call.mock_raw(|a, b| { 120 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 121 | }); 122 | } 123 | 124 | assert_eq!("mocked 2 true", struct_2.ref_method_with_call(true).await); 125 | assert_eq!(2, struct_2.0); 126 | } 127 | } 128 | 129 | mod and_method_is_assoc_method_with_ref { 130 | use super::*; 131 | 132 | #[tokio::test] 133 | async fn and_not_mocked_then_runs_normally() { 134 | assert_eq!("Hello World", Struct::assoc_method_with_ref("World").await); 135 | } 136 | 137 | #[tokio::test] 138 | async fn and_continue_mocked_then_runs_with_modified_args() { 139 | unsafe { 140 | Struct::assoc_method_with_ref.mock_raw(|_| MockResult::Continue(("Universe",))); 141 | } 142 | 143 | assert_eq!("Hello Universe", Struct::assoc_method_with_ref("World").await); 144 | } 145 | 146 | #[tokio::test] 147 | async fn and_return_mocked_then_returns_mocking_result() { 148 | unsafe { 149 | Struct::assoc_method_with_ref.mock_raw(|s| { 150 | MockResult::Return(Box::pin(async move { format!("Welcome {}", s) })) 151 | }); 152 | } 153 | 154 | assert_eq!("Welcome World", Struct::assoc_method_with_ref("World").await); 155 | } 156 | } 157 | 158 | mod and_method_is_assoc_method_with_ref_and_lifetime { 159 | use super::*; 160 | 161 | #[tokio::test] 162 | async fn and_not_mocked_then_runs_normally() { 163 | assert_eq!("Hello World", Struct::assoc_method_with_ref_and_lifetime("Hello", "World").await); 164 | } 165 | 166 | #[tokio::test] 167 | async fn and_continue_mocked_then_runs_with_modified_args() { 168 | unsafe { 169 | Struct::assoc_method_with_ref_and_lifetime.mock_raw(|s1, _| MockResult::Continue((s1, "Universe",))); 170 | } 171 | 172 | assert_eq!("Hello Universe", Struct::assoc_method_with_ref_and_lifetime("Hello", "World").await); 173 | } 174 | 175 | #[tokio::test] 176 | async fn and_return_mocked_then_returns_mocking_result() { 177 | unsafe { 178 | Struct::assoc_method_with_ref_and_lifetime.mock_raw(|_, s2| { 179 | MockResult::Return(Box::pin(async move { format!("Welcome {}", s2) })) 180 | }); 181 | } 182 | 183 | assert_eq!("Welcome World", Struct::assoc_method_with_ref_and_lifetime("Hello", "World").await); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /tests/mocking_methods_async/when_struct_generic_method_generic_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(T); 4 | 5 | #[mockable] 6 | impl Struct { 7 | async fn static_method(arg: bool, method_generic: U) -> String { 8 | format!("{} {}", arg, method_generic) 9 | } 10 | 11 | async fn ref_method(&self, arg: bool, method_generic: U) -> String { 12 | format!("{} {} {}", self.0, arg, method_generic) 13 | } 14 | 15 | async fn ref_mut_method(&mut self, arg: bool, method_generic: U) -> String { 16 | self.0 = T::default(); 17 | format!("{} {} {}", self.0, arg, method_generic) 18 | } 19 | 20 | async fn val_method(self, arg: bool, method_generic: U) -> String { 21 | format!("{} {} {}", self.0, arg, method_generic) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[tokio::test] 29 | async fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true 2.5", Struct::::static_method(true, 2.5f32).await); 31 | assert_eq!("true abc", Struct::::static_method(true, "abc").await); 32 | assert_eq!( 33 | "true 2.5", 34 | Struct::<&str>::static_method(true, 2.5f32).await 35 | ); 36 | } 37 | 38 | #[tokio::test] 39 | async fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 40 | unsafe { 41 | Struct::::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 42 | } 43 | 44 | assert_eq!("false 3.5", Struct::::static_method(true, 2.5f32).await); 45 | assert_eq!("true abc", Struct::::static_method(true, "abc").await); 46 | assert_eq!( 47 | "true 2.5", 48 | Struct::<&str>::static_method(true, 2.5f32).await 49 | ); 50 | } 51 | 52 | #[tokio::test] 53 | async fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 54 | unsafe { 55 | Struct::::static_method::.mock_raw(|a, b| { 56 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a, b) })) 57 | }); 58 | } 59 | 60 | assert_eq!( 61 | "mocked true 2.5", 62 | Struct::::static_method(true, 2.5f32).await 63 | ); 64 | assert_eq!("true abc", Struct::::static_method(true, "abc").await); 65 | assert_eq!( 66 | "true 2.5", 67 | Struct::<&str>::static_method(true, 2.5f32).await 68 | ); 69 | } 70 | } 71 | 72 | mod and_method_is_ref_method { 73 | use super::*; 74 | 75 | #[tokio::test] 76 | async fn and_not_mocked_then_runs_normally() { 77 | assert_eq!("2 true 1.5", Struct(2u8).ref_method(true, 1.5f32).await); 78 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc").await); 79 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32).await); 80 | } 81 | 82 | #[tokio::test] 83 | async fn and_continue_mocked_then_runs_with_modified_args() { 84 | let struct_2 = Struct(2u8); 85 | let struct_3 = Struct(3u8); 86 | unsafe { 87 | Struct::::ref_method:: 88 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 89 | } 90 | 91 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32).await); 92 | assert_eq!(2, struct_2.0); 93 | assert_eq!(3, struct_3.0); 94 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc").await); 95 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32).await); 96 | } 97 | 98 | #[tokio::test] 99 | async fn and_return_mocked_then_returns_mocking_result() { 100 | let struct_2 = Struct(2u8); 101 | unsafe { 102 | Struct::::ref_method::.mock_raw(|a, b, c| { 103 | MockResult::Return(Box::pin( 104 | async move { format!("mocked {} {} {}", a.0, b, c) }, 105 | )) 106 | }); 107 | } 108 | 109 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32).await); 110 | assert_eq!(2, struct_2.0); 111 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc").await); 112 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32).await); 113 | } 114 | } 115 | 116 | mod and_method_is_ref_mut_method { 117 | use super::*; 118 | 119 | #[tokio::test] 120 | async fn and_not_mocked_then_runs_normally() { 121 | let mut struct_2 = Struct(2u8); 122 | let mut struct_4 = Struct(4u8); 123 | let mut struct_str = Struct("abc"); 124 | 125 | assert_eq!("0 true 1.5", struct_2.ref_mut_method(true, 1.5f32).await); 126 | assert_eq!(0, struct_2.0); 127 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc").await); 128 | assert_eq!(0, struct_4.0); 129 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5).await); 130 | assert_eq!("", struct_str.0); 131 | } 132 | 133 | #[tokio::test] 134 | async fn and_continue_mocked_then_runs_with_modified_args() { 135 | let mut struct_2 = Struct(2u8); 136 | let struct_3 = Struct(3u8); 137 | let mut struct_4 = Struct(4u8); 138 | let mut struct_str = Struct("abc"); 139 | unsafe { 140 | Struct::::ref_mut_method:: 141 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 142 | } 143 | 144 | assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32).await); 145 | assert_eq!(2, struct_2.0); 146 | assert_eq!(0, struct_3.0); 147 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc").await); 148 | assert_eq!(0, struct_4.0); 149 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5).await); 150 | assert_eq!("", struct_str.0); 151 | } 152 | 153 | #[tokio::test] 154 | async fn and_return_mocked_then_returns_mocking_result() { 155 | let mut struct_2 = Struct(2u8); 156 | let mut struct_4 = Struct(4u8); 157 | let mut struct_str = Struct("abc"); 158 | unsafe { 159 | Struct::::ref_mut_method::.mock_raw(|a, b, c| { 160 | MockResult::Return(Box::pin( 161 | async move { format!("mocked {} {} {}", a.0, b, c) }, 162 | )) 163 | }); 164 | } 165 | 166 | assert_eq!( 167 | "mocked 2 true 1.5", 168 | struct_2.ref_mut_method(true, 1.5f32).await 169 | ); 170 | assert_eq!(2, struct_2.0); 171 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc").await); 172 | assert_eq!(0, struct_4.0); 173 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5).await); 174 | assert_eq!("", struct_str.0); 175 | } 176 | } 177 | 178 | mod and_method_is_val_method { 179 | use super::*; 180 | 181 | #[tokio::test] 182 | async fn and_not_mocked_then_runs_normally() { 183 | assert_eq!("2 true 1.5", Struct(2u8).val_method(true, 1.5f32).await); 184 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc").await); 185 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32).await); 186 | } 187 | 188 | #[tokio::test] 189 | async fn and_continue_mocked_then_runs_with_modified_args() { 190 | unsafe { 191 | Struct::::val_method:: 192 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3u8), !b, c + 1.))); 193 | } 194 | 195 | assert_eq!("3 false 2.5", Struct(2u8).val_method(true, 1.5f32).await); 196 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc").await); 197 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32).await); 198 | } 199 | 200 | #[tokio::test] 201 | async fn and_return_mocked_then_returns_mocking_result() { 202 | unsafe { 203 | Struct::::val_method::.mock_raw(|a, b, c| { 204 | MockResult::Return(Box::pin( 205 | async move { format!("mocked {} {} {}", a.0, b, c) }, 206 | )) 207 | }); 208 | } 209 | 210 | assert_eq!( 211 | "mocked 2 true 1.5", 212 | Struct(2u8).val_method(true, 1.5f32).await 213 | ); 214 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc").await); 215 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32).await); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /tests/mocking_methods_async/when_struct_generic_method_regular_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(T); 4 | 5 | #[mockable] 6 | impl Struct { 7 | async fn static_method(arg: bool) -> String { 8 | format!("{}", arg) 9 | } 10 | 11 | async fn ref_method(&self, arg: bool) -> String { 12 | format!("{} {}", self.0, arg) 13 | } 14 | 15 | async fn ref_mut_method(&mut self, arg: bool) -> String { 16 | self.0 = T::default(); 17 | format!("{} {}", self.0, arg) 18 | } 19 | 20 | async fn val_method(self, arg: bool) -> String { 21 | format!("{} {}", self.0, arg) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[tokio::test] 29 | async fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true", Struct::::static_method(true).await); 31 | assert_eq!("true", Struct::<&str>::static_method(true).await); 32 | } 33 | 34 | #[tokio::test] 35 | async fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 36 | unsafe { 37 | Struct::::static_method.mock_raw(|a| MockResult::Continue((!a,))); 38 | } 39 | 40 | assert_eq!("false", Struct::::static_method(true).await); 41 | assert_eq!("true", Struct::<&str>::static_method(true).await); 42 | } 43 | 44 | #[tokio::test] 45 | async fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 46 | unsafe { 47 | Struct::::static_method 48 | .mock_raw(|a| MockResult::Return(Box::pin(async move { format!("mocked {}", a) }))); 49 | } 50 | 51 | assert_eq!("mocked true", Struct::::static_method(true).await); 52 | assert_eq!("true", Struct::<&str>::static_method(true).await); 53 | } 54 | } 55 | 56 | mod and_method_is_ref_method { 57 | use super::*; 58 | 59 | #[tokio::test] 60 | async fn and_not_mocked_then_runs_normally() { 61 | assert_eq!("2 true", Struct(2u8).ref_method(true).await); 62 | assert_eq!("abc true", Struct("abc").ref_method(true).await); 63 | } 64 | 65 | #[tokio::test] 66 | async fn and_continue_mocked_then_runs_with_modified_args() { 67 | let struct_2 = Struct(2u8); 68 | let struct_3 = Struct(3u8); 69 | unsafe { 70 | Struct::::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 71 | } 72 | 73 | assert_eq!("3 false", struct_2.ref_method(true).await); 74 | assert_eq!(2, struct_2.0); 75 | assert_eq!(3, struct_3.0); 76 | assert_eq!("abc true", Struct("abc").ref_method(true).await); 77 | } 78 | 79 | #[tokio::test] 80 | async fn and_return_mocked_then_returns_mocking_result() { 81 | let struct_2 = Struct(2u8); 82 | unsafe { 83 | Struct::::ref_method.mock_raw(|a, b| { 84 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 85 | }); 86 | } 87 | 88 | assert_eq!("mocked 2 true", struct_2.ref_method(true).await); 89 | assert_eq!(2, struct_2.0); 90 | assert_eq!("abc true", Struct("abc").ref_method(true).await); 91 | } 92 | } 93 | 94 | mod and_method_is_ref_mut_method { 95 | use super::*; 96 | 97 | #[tokio::test] 98 | async fn and_not_mocked_then_runs_normally() { 99 | let mut struct_2 = Struct(2u8); 100 | let mut struct_str = Struct("str"); 101 | 102 | assert_eq!("0 true", struct_2.ref_mut_method(true).await); 103 | assert_eq!(0, struct_2.0); 104 | assert_eq!(" true", struct_str.ref_mut_method(true).await); 105 | assert_eq!("", struct_str.0); 106 | } 107 | 108 | #[tokio::test] 109 | async fn and_continue_mocked_then_runs_with_modified_args() { 110 | let mut struct_2 = Struct(2u8); 111 | let struct_3 = Struct(3u8); 112 | let mut struct_str = Struct("str"); 113 | unsafe { 114 | Struct::::ref_mut_method 115 | .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 116 | } 117 | 118 | assert_eq!("0 false", struct_2.ref_mut_method(true).await); 119 | assert_eq!(2, struct_2.0); 120 | assert_eq!(0, struct_3.0); 121 | assert_eq!(" true", struct_str.ref_mut_method(true).await); 122 | assert_eq!("", struct_str.0); 123 | } 124 | 125 | #[tokio::test] 126 | async fn and_return_mocked_then_returns_mocking_result() { 127 | let mut struct_2 = Struct(2u8); 128 | let mut struct_str = Struct("str"); 129 | unsafe { 130 | Struct::::ref_mut_method.mock_raw(|a, b| { 131 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 132 | }); 133 | } 134 | 135 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true).await); 136 | assert_eq!(2, struct_2.0); 137 | assert_eq!(" true", struct_str.ref_mut_method(true).await); 138 | assert_eq!("", struct_str.0); 139 | } 140 | } 141 | 142 | mod and_method_is_val_method { 143 | use super::*; 144 | 145 | #[tokio::test] 146 | async fn and_not_mocked_then_runs_normally() { 147 | assert_eq!("2 true", Struct(2u8).val_method(true).await); 148 | assert_eq!("abc true", Struct("abc").val_method(true).await); 149 | } 150 | 151 | #[tokio::test] 152 | async fn and_continue_mocked_then_runs_with_modified_args() { 153 | unsafe { 154 | Struct::::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3u8), !b))); 155 | } 156 | 157 | assert_eq!("3 false", Struct(2u8).val_method(true).await); 158 | assert_eq!("abc true", Struct("abc").val_method(true).await); 159 | } 160 | 161 | #[tokio::test] 162 | async fn and_return_mocked_then_returns_mocking_result() { 163 | unsafe { 164 | Struct::::val_method.mock_raw(|a, b| { 165 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 166 | }); 167 | } 168 | 169 | assert_eq!("mocked 2 true", Struct(2u8).val_method(true).await); 170 | assert_eq!("abc true", Struct("abc").val_method(true).await); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /tests/mocking_methods_async/when_struct_regular_method_generic_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(u8); 4 | 5 | #[mockable] 6 | impl Struct { 7 | async fn static_method(arg: bool, method_generic: T) -> String { 8 | format!("{} {}", arg, method_generic) 9 | } 10 | 11 | async fn ref_method(&self, arg: bool, method_generic: T) -> String { 12 | format!("{} {} {}", self.0, arg, method_generic) 13 | } 14 | 15 | async fn ref_mut_method(&mut self, arg: bool, method_generic: T) -> String { 16 | self.0 *= 2; 17 | format!("{} {} {}", self.0, arg, method_generic) 18 | } 19 | 20 | async fn val_method(self, arg: bool, method_generic: T) -> String { 21 | format!("{} {} {}", self.0, arg, method_generic) 22 | } 23 | } 24 | 25 | mod and_method_is_static { 26 | use super::*; 27 | 28 | #[tokio::test] 29 | async fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true 1.5", Struct::static_method(true, 1.5f32).await); 31 | assert_eq!("true abc", Struct::static_method(true, "abc").await); 32 | } 33 | 34 | #[tokio::test] 35 | async fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 36 | unsafe { 37 | Struct::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 38 | } 39 | 40 | assert_eq!("false 3.5", Struct::static_method(true, 2.5f32).await); 41 | assert_eq!("true abc", Struct::static_method(true, "abc").await); 42 | } 43 | 44 | #[tokio::test] 45 | async fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 46 | unsafe { 47 | Struct::static_method::.mock_raw(|a, b| { 48 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a, b) })) 49 | }); 50 | } 51 | 52 | assert_eq!("mocked true 2.5", Struct::static_method(true, 2.5f32).await); 53 | assert_eq!("true abc", Struct::static_method(true, "abc").await); 54 | } 55 | } 56 | 57 | mod and_method_is_ref_method { 58 | use super::*; 59 | 60 | #[tokio::test] 61 | async fn and_not_mocked_then_runs_normally() { 62 | assert_eq!("2 true 1.5", Struct(2).ref_method(true, 1.5f32).await); 63 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc").await); 64 | } 65 | 66 | #[tokio::test] 67 | async fn and_continue_mocked_then_runs_with_modified_args() { 68 | let struct_2 = Struct(2); 69 | let struct_3 = Struct(3); 70 | unsafe { 71 | Struct::ref_method:: 72 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 73 | } 74 | 75 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32).await); 76 | assert_eq!(2, struct_2.0); 77 | assert_eq!(3, struct_3.0); 78 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc").await); 79 | } 80 | 81 | #[tokio::test] 82 | async fn and_return_mocked_then_returns_mocking_result() { 83 | let struct_2 = Struct(2); 84 | unsafe { 85 | Struct::ref_method::.mock_raw(|a, b, c| { 86 | MockResult::Return(Box::pin( 87 | async move { format!("mocked {} {} {}", a.0, b, c) }, 88 | )) 89 | }); 90 | } 91 | 92 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32).await); 93 | assert_eq!(2, struct_2.0); 94 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc").await); 95 | } 96 | } 97 | 98 | mod and_method_is_ref_mut_method { 99 | use super::*; 100 | 101 | #[tokio::test] 102 | async fn and_not_mocked_then_runs_normally() { 103 | let mut struct_2 = Struct(2); 104 | let mut struct_4 = Struct(4); 105 | 106 | assert_eq!("4 true 1.5", struct_2.ref_mut_method(true, 1.5f32).await); 107 | assert_eq!(4, struct_2.0); 108 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc").await); 109 | assert_eq!(8, struct_4.0); 110 | } 111 | 112 | #[tokio::test] 113 | async fn and_continue_mocked_then_runs_with_modified_args() { 114 | let mut struct_2 = Struct(2); 115 | let struct_3 = Struct(3); 116 | let mut struct_4 = Struct(4); 117 | unsafe { 118 | Struct::ref_mut_method:: 119 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 120 | } 121 | 122 | assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32).await); 123 | assert_eq!(2, struct_2.0); 124 | assert_eq!(6, struct_3.0); 125 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc").await); 126 | assert_eq!(8, struct_4.0); 127 | } 128 | 129 | #[tokio::test] 130 | async fn and_return_mocked_then_returns_mocking_result() { 131 | let mut struct_2 = Struct(2); 132 | let mut struct_4 = Struct(4); 133 | unsafe { 134 | Struct::ref_mut_method::.mock_raw(|a, b, c| { 135 | MockResult::Return(Box::pin( 136 | async move { format!("mocked {} {} {}", a.0, b, c) }, 137 | )) 138 | }); 139 | } 140 | 141 | assert_eq!( 142 | "mocked 2 true 1.5", 143 | struct_2.ref_mut_method(true, 1.5f32).await 144 | ); 145 | assert_eq!(2, struct_2.0); 146 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc").await); 147 | assert_eq!(8, struct_4.0); 148 | } 149 | } 150 | 151 | mod and_method_is_val_method { 152 | use super::*; 153 | 154 | #[tokio::test] 155 | async fn and_not_mocked_then_runs_normally() { 156 | assert_eq!("2 true 1.5", Struct(2).val_method(true, 1.5f32).await); 157 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc").await); 158 | } 159 | 160 | #[tokio::test] 161 | async fn and_continue_mocked_then_runs_with_modified_args() { 162 | unsafe { 163 | Struct::val_method:: 164 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3), !b, c + 1.))); 165 | } 166 | 167 | assert_eq!("3 false 2.5", Struct(2).val_method(true, 1.5f32).await); 168 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc").await); 169 | } 170 | 171 | #[tokio::test] 172 | async fn and_return_mocked_then_returns_mocking_result() { 173 | unsafe { 174 | Struct::val_method::.mock_raw(|a, b, c| { 175 | MockResult::Return(Box::pin( 176 | async move { format!("mocked {} {} {}", a.0, b, c) }, 177 | )) 178 | }); 179 | } 180 | 181 | assert_eq!( 182 | "mocked 2 true 1.5", 183 | Struct(2).val_method(true, 1.5f32).await 184 | ); 185 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc").await); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /tests/mocking_methods_async/when_struct_regular_method_regular_async.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | struct Struct(u8); 4 | 5 | #[mockable] 6 | impl Struct { 7 | async fn static_method(arg: bool) -> String { 8 | format!("{}", arg) 9 | } 10 | 11 | async fn ref_method(&self, arg: bool) -> String { 12 | format!("{} {}", self.0, arg) 13 | } 14 | 15 | async fn ref_mut_method(&mut self, arg: bool) -> String { 16 | self.0 *= 2; 17 | format!("{} {}", self.0, arg) 18 | } 19 | 20 | async fn val_method(self, arg: bool) -> String { 21 | format!("{} {}", self.0, arg) 22 | } 23 | } 24 | 25 | mod and_async_method_is_static { 26 | use super::*; 27 | 28 | #[tokio::test] 29 | async fn and_not_mocked_then_runs_normally() { 30 | assert_eq!("true", Struct::static_method(true).await); 31 | } 32 | 33 | #[tokio::test] 34 | async fn and_continue_mocked_then_runs_with_modified_args() { 35 | unsafe { 36 | Struct::static_method.mock_raw(|a| MockResult::Continue((!a,))); 37 | } 38 | 39 | assert_eq!("false", Struct::static_method(true).await); 40 | } 41 | 42 | #[tokio::test] 43 | async fn and_return_mocked_then_returns_mocking_result() { 44 | unsafe { 45 | Struct::static_method 46 | .mock_raw(|a| MockResult::Return(Box::pin(async move { format!("mocked {}", a) }))); 47 | } 48 | 49 | assert_eq!("mocked true", Struct::static_method(true).await); 50 | } 51 | } 52 | 53 | mod and_method_is_ref_method { 54 | use super::*; 55 | 56 | #[tokio::test] 57 | async fn and_not_mocked_then_runs_normally() { 58 | assert_eq!("2 true", Struct(2).ref_method(true).await); 59 | } 60 | 61 | #[tokio::test] 62 | async fn and_continue_mocked_then_runs_with_modified_args() { 63 | let struct_2 = Struct(2); 64 | let struct_3 = Struct(3); 65 | unsafe { 66 | Struct::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 67 | } 68 | 69 | assert_eq!("3 false", struct_2.ref_method(true).await); 70 | assert_eq!(2, struct_2.0); 71 | assert_eq!(3, struct_3.0); 72 | } 73 | 74 | #[tokio::test] 75 | async fn and_return_mocked_then_returns_mocking_result() { 76 | let struct_2 = Struct(2); 77 | unsafe { 78 | Struct::ref_method.mock_raw(|a, b| { 79 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 80 | }); 81 | } 82 | 83 | assert_eq!("mocked 2 true", struct_2.ref_method(true).await); 84 | assert_eq!(2, struct_2.0); 85 | } 86 | } 87 | 88 | mod and_async_method_is_ref_mut_method { 89 | use super::*; 90 | 91 | #[tokio::test] 92 | async fn and_not_mocked_then_runs_normally() { 93 | let mut struct_2 = Struct(2); 94 | 95 | assert_eq!("4 true", struct_2.ref_mut_method(true).await); 96 | assert_eq!(4, struct_2.0); 97 | } 98 | 99 | #[tokio::test] 100 | async fn and_continue_mocked_then_runs_with_modified_args() { 101 | let mut struct_2 = Struct(2); 102 | let struct_3 = Struct(3); 103 | unsafe { 104 | Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 105 | } 106 | 107 | assert_eq!("6 false", struct_2.ref_mut_method(true).await); 108 | assert_eq!(2, struct_2.0); 109 | assert_eq!(6, struct_3.0); 110 | } 111 | 112 | #[tokio::test] 113 | async fn and_return_mocked_then_returns_mocking_result() { 114 | let mut struct_2 = Struct(2); 115 | unsafe { 116 | Struct::ref_mut_method.mock_raw(|a, b| { 117 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 118 | }); 119 | } 120 | 121 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true).await); 122 | assert_eq!(2, struct_2.0); 123 | } 124 | } 125 | 126 | mod and_async_method_is_val_method { 127 | use super::*; 128 | 129 | #[tokio::test] 130 | async fn and_not_mocked_then_runs_normally() { 131 | assert_eq!("2 true", Struct(2).val_method(true).await); 132 | } 133 | 134 | #[tokio::test] 135 | async fn and_continue_mocked_then_runs_with_modified_args() { 136 | unsafe { 137 | Struct::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3), !b))); 138 | } 139 | 140 | assert_eq!("3 false", Struct(2).val_method(true).await); 141 | } 142 | 143 | #[tokio::test] 144 | async fn and_return_mocked_then_returns_mocking_result() { 145 | unsafe { 146 | Struct::val_method.mock_raw(|a, b| { 147 | MockResult::Return(Box::pin(async move { format!("mocked {} {}", a.0, b) })) 148 | }); 149 | } 150 | 151 | assert_eq!("mocked 2 true", Struct(2).val_method(true).await); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/mod.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | mod when_trait_generic_struct_generic_method_generic; 4 | mod when_trait_generic_struct_generic_method_regular; 5 | mod when_trait_generic_struct_regular_method_generic; 6 | mod when_trait_generic_struct_regular_method_regular; 7 | mod when_trait_regular_struct_generic_method_generic; 8 | mod when_trait_regular_struct_generic_method_regular; 9 | mod when_trait_regular_struct_regular_method_generic; 10 | mod when_trait_regular_struct_regular_method_regular; 11 | 12 | mod mocking_default_impl_of_trait_of_struct { 13 | use super::*; 14 | 15 | #[mockable] 16 | trait Trait { 17 | fn method() -> &'static str { 18 | "not mocked" 19 | } 20 | } 21 | 22 | struct Struct1; 23 | 24 | impl Trait for Struct1 {} 25 | 26 | struct Struct2; 27 | 28 | impl Trait for Struct2 {} 29 | 30 | #[test] 31 | fn does_not_mock_default_impl_of_other_struct() { 32 | unsafe { 33 | Struct1::method.mock_raw(|| MockResult::Return("mocked")); 34 | } 35 | 36 | assert_eq!("mocked", Struct1::method()); 37 | assert_eq!("not mocked", Struct2::method()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool, trait_generic: V) -> String { 6 | format!("{} {}", arg, trait_generic) 7 | } 8 | 9 | fn ref_method(&self, arg: bool, trait_generic: V) -> String { 10 | format!("{} {} {}", self.to_string(), arg, trait_generic) 11 | } 12 | 13 | fn ref_mut_method(&mut self, arg: bool, trait_generic: V) -> String { 14 | self.modify(); 15 | format!("{} {} {}", self.to_string(), arg, trait_generic) 16 | } 17 | 18 | fn val_method(self, arg: bool, trait_generic: V) -> String { 19 | format!("{} {} {}", self.to_string(), arg, trait_generic) 20 | } 21 | 22 | fn to_string(&self) -> String; 23 | fn modify(&mut self); 24 | } 25 | 26 | struct Struct(T); 27 | 28 | impl Trait for Struct { 29 | fn to_string(&self) -> String { 30 | self.0.to_string() 31 | } 32 | 33 | fn modify(&mut self) { 34 | self.0 = T::default(); 35 | } 36 | } 37 | 38 | mod and_method_is_static { 39 | use super::*; 40 | 41 | #[test] 42 | fn and_not_mocked_then_runs_normally() { 43 | assert_eq!("true a", Struct::::static_method(true, 'a')); 44 | assert_eq!("true a", Struct::<&str>::static_method(true, 'a')); 45 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 46 | } 47 | 48 | #[test] 49 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 50 | unsafe { 51 | as Trait>::static_method 52 | .mock_raw(|a, b| MockResult::Continue((!a, b.to_ascii_uppercase()))); 53 | } 54 | 55 | assert_eq!("false A", Struct::::static_method(true, 'a')); 56 | assert_eq!("true a", Struct::<&str>::static_method(true, 'a')); 57 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 58 | } 59 | 60 | #[test] 61 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 62 | unsafe { 63 | as Trait>::static_method 64 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 65 | } 66 | 67 | assert_eq!("mocked true a", Struct::::static_method(true, 'a')); 68 | assert_eq!("true a", Struct::<&str>::static_method(true, 'a')); 69 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 70 | } 71 | } 72 | 73 | mod and_method_is_ref_method { 74 | use super::*; 75 | 76 | #[test] 77 | fn and_not_mocked_then_runs_normally() { 78 | assert_eq!("2 true a", Struct(2u8).ref_method(true, 'a')); 79 | assert_eq!("abc true a", Struct("abc").ref_method(true, 'a')); 80 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 81 | } 82 | 83 | #[test] 84 | fn and_continue_mocked_then_runs_with_modified_args() { 85 | let struct_2 = Struct(2u8); 86 | let struct_3 = Struct(3u8); 87 | unsafe { 88 | as Trait>::ref_method 89 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c.to_ascii_uppercase()))); 90 | } 91 | 92 | assert_eq!("3 false A", struct_2.ref_method(true, 'a')); 93 | assert_eq!(2, struct_2.0); 94 | assert_eq!(3, struct_3.0); 95 | assert_eq!("abc true a", Struct("abc").ref_method(true, 'a')); 96 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 97 | } 98 | 99 | #[test] 100 | fn and_return_mocked_then_returns_mocking_result() { 101 | let struct_2 = Struct(2u8); 102 | unsafe { 103 | as Trait>::ref_method 104 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 105 | } 106 | 107 | assert_eq!("mocked 2 true a", struct_2.ref_method(true, 'a')); 108 | assert_eq!(2, struct_2.0); 109 | assert_eq!("abc true a", Struct("abc").ref_method(true, 'a')); 110 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 111 | } 112 | } 113 | 114 | mod and_method_is_ref_mut_method { 115 | use super::*; 116 | 117 | #[test] 118 | fn and_not_mocked_then_runs_normally() { 119 | let mut struct_2 = Struct(2u8); 120 | let mut struct_str = Struct("str"); 121 | let mut struct_4 = Struct(4u8); 122 | 123 | assert_eq!("0 true a", struct_2.ref_mut_method(true, 'a')); 124 | assert_eq!(0, struct_2.0); 125 | assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); 126 | assert_eq!("", struct_str.0); 127 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 128 | assert_eq!(0, struct_4.0); 129 | } 130 | 131 | #[test] 132 | fn and_continue_mocked_then_runs_with_modified_args() { 133 | let mut struct_2 = Struct(2u8); 134 | let struct_3 = Struct(3u8); 135 | let mut struct_str = Struct("str"); 136 | let mut struct_4 = Struct(4u8); 137 | unsafe { 138 | as Trait>::ref_mut_method.mock_raw(|_, b, c| { 139 | MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) 140 | }); 141 | } 142 | 143 | assert_eq!("0 false A", struct_2.ref_mut_method(true, 'a')); 144 | assert_eq!(2, struct_2.0); 145 | assert_eq!(0, struct_3.0); 146 | assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); 147 | assert_eq!("", struct_str.0); 148 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 149 | assert_eq!(0, struct_4.0); 150 | } 151 | 152 | #[test] 153 | fn and_return_mocked_then_returns_mocking_result() { 154 | let mut struct_2 = Struct(2u8); 155 | let mut struct_str = Struct("str"); 156 | let mut struct_4 = Struct(4u8); 157 | unsafe { 158 | as Trait>::ref_mut_method 159 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 160 | } 161 | 162 | assert_eq!("mocked 2 true a", struct_2.ref_mut_method(true, 'a')); 163 | assert_eq!(2, struct_2.0); 164 | assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); 165 | assert_eq!("", struct_str.0); 166 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 167 | assert_eq!(0, struct_4.0); 168 | } 169 | } 170 | 171 | mod and_method_is_val_method { 172 | use super::*; 173 | 174 | #[test] 175 | fn and_not_mocked_then_runs_normally() { 176 | assert_eq!("2 true a", Struct(2u8).val_method(true, 'a')); 177 | assert_eq!("abc true a", Struct("abc").val_method(true, 'a')); 178 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 179 | } 180 | 181 | #[test] 182 | fn and_continue_mocked_then_runs_with_modified_args() { 183 | unsafe { 184 | as Trait>::val_method.mock_raw(move |_, b, c| { 185 | MockResult::Continue((Struct(3u8), !b, c.to_ascii_uppercase())) 186 | }); 187 | } 188 | 189 | assert_eq!("3 false A", Struct(2u8).val_method(true, 'a')); 190 | assert_eq!("abc true a", Struct("abc").val_method(true, 'a')); 191 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 192 | } 193 | 194 | #[test] 195 | fn and_return_mocked_then_returns_mocking_result() { 196 | unsafe { 197 | as Trait>::val_method 198 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 199 | } 200 | 201 | assert_eq!("mocked 2 true a", Struct(2u8).val_method(true, 'a')); 202 | assert_eq!("abc true a", Struct("abc").val_method(true, 'a')); 203 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool, method_generic: T, trait_generic: V) -> String { 6 | format!("{} {} {}", arg, method_generic, trait_generic) 7 | } 8 | 9 | fn ref_method(&self, arg: bool, method_generic: T, trait_generic: V) -> String { 10 | format!( 11 | "{} {} {} {}", 12 | self.to_string(), 13 | arg, 14 | method_generic, 15 | trait_generic 16 | ) 17 | } 18 | 19 | fn ref_mut_method( 20 | &mut self, 21 | arg: bool, 22 | method_generic: T, 23 | trait_generic: V, 24 | ) -> String { 25 | self.modify(); 26 | format!( 27 | "{} {} {} {}", 28 | self.to_string(), 29 | arg, 30 | method_generic, 31 | trait_generic 32 | ) 33 | } 34 | 35 | fn val_method(self, arg: bool, method_generic: T, trait_generic: V) -> String { 36 | format!( 37 | "{} {} {} {}", 38 | self.to_string(), 39 | arg, 40 | method_generic, 41 | trait_generic 42 | ) 43 | } 44 | 45 | fn to_string(&self) -> String; 46 | fn modify(&mut self); 47 | } 48 | 49 | struct Struct(u8); 50 | 51 | impl Trait for Struct { 52 | fn to_string(&self) -> String { 53 | self.0.to_string() 54 | } 55 | 56 | fn modify(&mut self) { 57 | self.0 *= 2; 58 | } 59 | } 60 | 61 | mod and_method_is_static { 62 | use super::*; 63 | 64 | #[test] 65 | fn and_not_mocked_then_runs_normally() { 66 | assert_eq!("true 1.5 a", Struct::static_method(true, 1.5f32, 'a')); 67 | assert_eq!("true abc a", Struct::static_method(true, "abc", 'a')); 68 | assert_eq!("true 1.5 abc", Struct::static_method(true, 1.5f32, "abc")); 69 | } 70 | 71 | #[test] 72 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 73 | unsafe { 74 | >::static_method:: 75 | .mock_raw(|a, b, c| MockResult::Continue((!a, b + 1., c.to_ascii_uppercase()))); 76 | } 77 | 78 | assert_eq!("false 3.5 A", Struct::static_method(true, 2.5f32, 'a')); 79 | assert_eq!("true abc a", Struct::static_method(true, "abc", 'a')); 80 | assert_eq!("true 1.5 abc", Struct::static_method(true, 1.5f32, "abc")); 81 | } 82 | 83 | #[test] 84 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 85 | unsafe { 86 | >::static_method:: 87 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a, b, c))); 88 | } 89 | 90 | assert_eq!( 91 | "mocked true 2.5 a", 92 | Struct::static_method(true, 2.5f32, 'a') 93 | ); 94 | assert_eq!("true abc a", Struct::static_method(true, "abc", 'a')); 95 | assert_eq!("true 1.5 abc", Struct::static_method(true, 1.5f32, "abc")); 96 | } 97 | } 98 | 99 | mod and_method_is_ref_method { 100 | use super::*; 101 | 102 | #[test] 103 | fn and_not_mocked_then_runs_normally() { 104 | assert_eq!("2 true 1.5 a", Struct(2).ref_method(true, 1.5f32, 'a')); 105 | assert_eq!("2 true abc a", Struct(2).ref_method(true, "abc", 'a')); 106 | assert_eq!("2 true 1.5 abc", Struct(2).ref_method(true, 1.5f32, "abc")); 107 | } 108 | 109 | #[test] 110 | fn and_continue_mocked_then_runs_with_modified_args() { 111 | let struct_2 = Struct(2); 112 | let struct_3 = Struct(3); 113 | unsafe { 114 | >::ref_method::.mock_raw(|_, b, c, d| { 115 | MockResult::Continue((&struct_3, !b, c + 1., d.to_ascii_uppercase())) 116 | }); 117 | } 118 | 119 | assert_eq!("3 false 2.5 A", struct_2.ref_method(true, 1.5f32, 'a')); 120 | assert_eq!(2, struct_2.0); 121 | assert_eq!(3, struct_3.0); 122 | assert_eq!("2 true abc a", Struct(2).ref_method(true, "abc", 'a')); 123 | assert_eq!("2 true 1.5 abc", Struct(2).ref_method(true, 1.5f32, "abc")); 124 | } 125 | 126 | #[test] 127 | fn and_return_mocked_then_returns_mocking_result() { 128 | let struct_2 = Struct(2); 129 | unsafe { 130 | >::ref_method::.mock_raw(|a, b, c, d| { 131 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 132 | }); 133 | } 134 | 135 | assert_eq!( 136 | "mocked 2 true 1.5 a", 137 | struct_2.ref_method(true, 1.5f32, 'a') 138 | ); 139 | assert_eq!(2, struct_2.0); 140 | assert_eq!("2 true abc a", Struct(2).ref_method(true, "abc", 'a')); 141 | assert_eq!("2 true 1.5 abc", Struct(2).ref_method(true, 1.5f32, "abc")); 142 | } 143 | } 144 | 145 | mod and_method_is_ref_mut_method { 146 | use super::*; 147 | 148 | #[test] 149 | fn and_not_mocked_then_runs_normally() { 150 | let mut struct_2 = Struct(2); 151 | let mut struct_4 = Struct(4); 152 | let mut struct_5 = Struct(5); 153 | 154 | assert_eq!("4 true 1.5 a", struct_2.ref_mut_method(true, 1.5f32, 'a')); 155 | assert_eq!(4, struct_2.0); 156 | assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 157 | assert_eq!(8, struct_4.0); 158 | assert_eq!( 159 | "10 true 1.5 abc", 160 | struct_5.ref_mut_method(true, 1.5f32, "abc") 161 | ); 162 | assert_eq!(10, struct_5.0); 163 | } 164 | 165 | #[test] 166 | fn and_continue_mocked_then_runs_with_modified_args() { 167 | let mut struct_2 = Struct(2); 168 | let struct_3 = Struct(3); 169 | let mut struct_4 = Struct(4); 170 | let mut struct_5 = Struct(5); 171 | unsafe { 172 | >::ref_mut_method::.mock_raw(|_, b, c, d| { 173 | MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) 174 | }); 175 | } 176 | 177 | assert_eq!("6 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); 178 | assert_eq!(2, struct_2.0); 179 | assert_eq!(6, struct_3.0); 180 | assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 181 | assert_eq!(8, struct_4.0); 182 | assert_eq!( 183 | "10 true 1.5 abc", 184 | struct_5.ref_mut_method(true, 1.5f32, "abc") 185 | ); 186 | assert_eq!(10, struct_5.0); 187 | } 188 | 189 | #[test] 190 | fn and_return_mocked_then_returns_mocking_result() { 191 | let mut struct_2 = Struct(2); 192 | let mut struct_4 = Struct(4); 193 | let mut struct_5 = Struct(5); 194 | unsafe { 195 | >::ref_mut_method::.mock_raw(|a, b, c, d| { 196 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 197 | }); 198 | } 199 | 200 | assert_eq!( 201 | "mocked 2 true 1.5 a", 202 | struct_2.ref_mut_method(true, 1.5f32, 'a') 203 | ); 204 | assert_eq!(2, struct_2.0); 205 | assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 206 | assert_eq!(8, struct_4.0); 207 | assert_eq!( 208 | "10 true 1.5 abc", 209 | struct_5.ref_mut_method(true, 1.5f32, "abc") 210 | ); 211 | assert_eq!(10, struct_5.0); 212 | } 213 | } 214 | 215 | mod and_method_is_val_method { 216 | use super::*; 217 | 218 | #[test] 219 | fn and_not_mocked_then_runs_normally() { 220 | assert_eq!("2 true 1.5 a", Struct(2).val_method(true, 1.5f32, 'a')); 221 | assert_eq!("2 true abc a", Struct(2).val_method(true, "abc", 'a')); 222 | assert_eq!("2 true 1.5 abc", Struct(2).val_method(true, 1.5f32, "abc")); 223 | } 224 | 225 | #[test] 226 | fn and_continue_mocked_then_runs_with_modified_args() { 227 | unsafe { 228 | >::val_method::.mock_raw(move |_, b, c, d| { 229 | MockResult::Continue((Struct(3), !b, c + 1., d.to_ascii_uppercase())) 230 | }); 231 | } 232 | 233 | assert_eq!("3 false 2.5 A", Struct(2).val_method(true, 1.5f32, 'a')); 234 | assert_eq!("2 true abc a", Struct(2).val_method(true, "abc", 'a')); 235 | assert_eq!("2 true 1.5 abc", Struct(2).val_method(true, 1.5f32, "abc")); 236 | } 237 | 238 | #[test] 239 | fn and_return_mocked_then_returns_mocking_result() { 240 | unsafe { 241 | >::val_method::.mock_raw(|a, b, c, d| { 242 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 243 | }); 244 | } 245 | 246 | assert_eq!( 247 | "mocked 2 true 1.5 a", 248 | Struct(2).val_method(true, 1.5f32, 'a') 249 | ); 250 | assert_eq!("2 true abc a", Struct(2).val_method(true, "abc", 'a')); 251 | assert_eq!("2 true 1.5 abc", Struct(2).val_method(true, 1.5f32, "abc")); 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool, trait_generic: V) -> String { 6 | format!("{} {}", arg, trait_generic) 7 | } 8 | 9 | fn ref_method(&self, arg: bool, trait_generic: V) -> String { 10 | format!("{} {} {}", self.to_string(), arg, trait_generic) 11 | } 12 | 13 | fn ref_mut_method(&mut self, arg: bool, trait_generic: V) -> String { 14 | self.modify(); 15 | format!("{} {} {}", self.to_string(), arg, trait_generic) 16 | } 17 | 18 | fn val_method(self, arg: bool, trait_generic: V) -> String { 19 | format!("{} {} {}", self.to_string(), arg, trait_generic) 20 | } 21 | 22 | fn to_string(&self) -> String; 23 | fn modify(&mut self); 24 | } 25 | 26 | struct Struct(u8); 27 | 28 | impl Trait for Struct { 29 | fn to_string(&self) -> String { 30 | self.0.to_string() 31 | } 32 | 33 | fn modify(&mut self) { 34 | self.0 *= 2; 35 | } 36 | } 37 | 38 | mod and_method_is_static { 39 | use super::*; 40 | 41 | #[test] 42 | fn and_not_mocked_then_runs_normally() { 43 | assert_eq!("true a", Struct::static_method(true, 'a')); 44 | assert_eq!("true abc", Struct::static_method(true, "abc")); 45 | } 46 | 47 | #[test] 48 | fn and_continue_mocked_then_runs_with_modified_args() { 49 | unsafe { 50 | >::static_method 51 | .mock_raw(|a, b| MockResult::Continue((!a, b.to_ascii_uppercase()))); 52 | } 53 | 54 | assert_eq!("false A", Struct::static_method(true, 'a')); 55 | assert_eq!("true abc", Struct::static_method(true, "abc")); 56 | } 57 | 58 | #[test] 59 | fn and_return_mocked_then_returns_mocking_result() { 60 | unsafe { 61 | >::static_method 62 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 63 | } 64 | 65 | assert_eq!("mocked true a", Struct::static_method(true, 'a')); 66 | assert_eq!("true abc", Struct::static_method(true, "abc")); 67 | } 68 | } 69 | 70 | mod and_method_is_ref_method { 71 | use super::*; 72 | 73 | #[test] 74 | fn and_not_mocked_then_runs_normally() { 75 | assert_eq!("2 true a", Struct(2).ref_method(true, 'a')); 76 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 77 | } 78 | 79 | #[test] 80 | fn and_continue_mocked_then_runs_with_modified_args() { 81 | let struct_2 = Struct(2); 82 | let struct_3 = Struct(3); 83 | unsafe { 84 | >::ref_method 85 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c.to_ascii_uppercase()))); 86 | } 87 | 88 | assert_eq!("3 false A", struct_2.ref_method(true, 'a')); 89 | assert_eq!(2, struct_2.0); 90 | assert_eq!(3, struct_3.0); 91 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 92 | } 93 | 94 | #[test] 95 | fn and_return_mocked_then_returns_mocking_result() { 96 | let struct_2 = Struct(2); 97 | unsafe { 98 | >::ref_method 99 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 100 | } 101 | 102 | assert_eq!("mocked 2 true a", struct_2.ref_method(true, 'a')); 103 | assert_eq!(2, struct_2.0); 104 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 105 | } 106 | } 107 | 108 | mod and_method_is_ref_mut_method { 109 | use super::*; 110 | 111 | #[test] 112 | fn and_not_mocked_then_runs_normally() { 113 | let mut struct_2 = Struct(2); 114 | let mut struct_4 = Struct(4); 115 | 116 | assert_eq!("4 true a", struct_2.ref_mut_method(true, 'a')); 117 | assert_eq!(4, struct_2.0); 118 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 119 | assert_eq!(8, struct_4.0); 120 | } 121 | 122 | #[test] 123 | fn and_continue_mocked_then_runs_with_modified_args() { 124 | let mut struct_2 = Struct(2); 125 | let struct_3 = Struct(3); 126 | let mut struct_4 = Struct(4); 127 | unsafe { 128 | >::ref_mut_method.mock_raw(|_, b, c| { 129 | MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) 130 | }); 131 | } 132 | 133 | assert_eq!("6 false A", struct_2.ref_mut_method(true, 'a')); 134 | assert_eq!(2, struct_2.0); 135 | assert_eq!(6, struct_3.0); 136 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 137 | assert_eq!(8, struct_4.0); 138 | } 139 | 140 | #[test] 141 | fn and_return_mocked_then_returns_mocking_result() { 142 | let mut struct_2 = Struct(2); 143 | let mut struct_4 = Struct(4); 144 | unsafe { 145 | >::ref_mut_method 146 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 147 | } 148 | 149 | assert_eq!("mocked 2 true a", struct_2.ref_mut_method(true, 'a')); 150 | assert_eq!(2, struct_2.0); 151 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 152 | assert_eq!(8, struct_4.0); 153 | } 154 | } 155 | 156 | mod and_method_is_val_method { 157 | use super::*; 158 | 159 | #[test] 160 | fn and_not_mocked_then_runs_normally() { 161 | assert_eq!("2 true a", Struct(2).val_method(true, 'a')); 162 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 163 | } 164 | 165 | #[test] 166 | fn and_continue_mocked_then_runs_with_modified_args() { 167 | unsafe { 168 | >::val_method.mock_raw(move |_, b, c| { 169 | MockResult::Continue((Struct(3), !b, c.to_ascii_uppercase())) 170 | }); 171 | } 172 | 173 | assert_eq!("3 false A", Struct(2).val_method(true, 'a')); 174 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 175 | } 176 | 177 | #[test] 178 | fn and_return_mocked_then_returns_mocking_result() { 179 | unsafe { 180 | >::val_method 181 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 182 | } 183 | 184 | assert_eq!("mocked 2 true a", Struct(2).val_method(true, 'a')); 185 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool, method_generic: U) -> String { 6 | format!("{} {}", arg, method_generic) 7 | } 8 | 9 | fn ref_method(&self, arg: bool, method_generic: U) -> String { 10 | format!("{} {} {}", self.to_string(), arg, method_generic) 11 | } 12 | 13 | fn ref_mut_method(&mut self, arg: bool, method_generic: U) -> String { 14 | self.modify(); 15 | format!("{} {} {}", self.to_string(), arg, method_generic) 16 | } 17 | 18 | fn val_method(self, arg: bool, method_generic: U) -> String { 19 | format!("{} {} {}", self.to_string(), arg, method_generic) 20 | } 21 | 22 | fn to_string(&self) -> String; 23 | fn modify(&mut self); 24 | } 25 | 26 | struct Struct(T); 27 | 28 | impl Trait for Struct { 29 | fn to_string(&self) -> String { 30 | self.0.to_string() 31 | } 32 | 33 | fn modify(&mut self) { 34 | self.0 = T::default(); 35 | } 36 | } 37 | 38 | mod and_method_is_static { 39 | use super::*; 40 | 41 | #[test] 42 | fn and_not_mocked_then_runs_normally() { 43 | assert_eq!("true 2.5", Struct::::static_method(true, 2.5f32)); 44 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 45 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 46 | } 47 | 48 | #[test] 49 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 50 | unsafe { 51 | Struct::::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 52 | } 53 | 54 | assert_eq!("false 3.5", Struct::::static_method(true, 2.5f32)); 55 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 56 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 57 | } 58 | 59 | #[test] 60 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 61 | unsafe { 62 | Struct::::static_method:: 63 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 64 | } 65 | 66 | assert_eq!("mocked true 2.5", Struct::::static_method(true, 2.5f32)); 67 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 68 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 69 | } 70 | } 71 | 72 | mod and_method_is_ref_method { 73 | use super::*; 74 | 75 | #[test] 76 | fn and_not_mocked_then_runs_normally() { 77 | assert_eq!("2 true 1.5", Struct(2u8).ref_method(true, 1.5f32)); 78 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 79 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 80 | } 81 | 82 | #[test] 83 | fn and_continue_mocked_then_runs_with_modified_args() { 84 | let struct_2 = Struct(2u8); 85 | let struct_3 = Struct(3u8); 86 | unsafe { 87 | Struct::::ref_method:: 88 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 89 | } 90 | 91 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32)); 92 | assert_eq!(2, struct_2.0); 93 | assert_eq!(3, struct_3.0); 94 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 95 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 96 | } 97 | 98 | #[test] 99 | fn and_return_mocked_then_returns_mocking_result() { 100 | let struct_2 = Struct(2u8); 101 | unsafe { 102 | Struct::::ref_method:: 103 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 104 | } 105 | 106 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32)); 107 | assert_eq!(2, struct_2.0); 108 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 109 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 110 | } 111 | } 112 | 113 | mod and_method_is_ref_mut_method { 114 | use super::*; 115 | 116 | #[test] 117 | fn and_not_mocked_then_runs_normally() { 118 | let mut struct_2 = Struct(2u8); 119 | let mut struct_4 = Struct(4u8); 120 | let mut struct_str = Struct("abc"); 121 | 122 | assert_eq!("0 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 123 | assert_eq!(0, struct_2.0); 124 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 125 | assert_eq!(0, struct_4.0); 126 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 127 | assert_eq!("", struct_str.0); 128 | } 129 | 130 | #[test] 131 | fn and_continue_mocked_then_runs_with_modified_args() { 132 | let mut struct_2 = Struct(2u8); 133 | let struct_3 = Struct(3u8); 134 | let mut struct_4 = Struct(4u8); 135 | let mut struct_str = Struct("abc"); 136 | unsafe { 137 | Struct::::ref_mut_method:: 138 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 139 | } 140 | 141 | assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); 142 | assert_eq!(2, struct_2.0); 143 | assert_eq!(0, struct_3.0); 144 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 145 | assert_eq!(0, struct_4.0); 146 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 147 | assert_eq!("", struct_str.0); 148 | } 149 | 150 | #[test] 151 | fn and_return_mocked_then_returns_mocking_result() { 152 | let mut struct_2 = Struct(2u8); 153 | let mut struct_4 = Struct(4u8); 154 | let mut struct_str = Struct("abc"); 155 | unsafe { 156 | Struct::::ref_mut_method:: 157 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 158 | } 159 | 160 | assert_eq!("mocked 2 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 161 | assert_eq!(2, struct_2.0); 162 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 163 | assert_eq!(0, struct_4.0); 164 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 165 | assert_eq!("", struct_str.0); 166 | } 167 | } 168 | 169 | mod and_method_is_val_method { 170 | use super::*; 171 | 172 | #[test] 173 | fn and_not_mocked_then_runs_normally() { 174 | assert_eq!("2 true 1.5", Struct(2u8).val_method(true, 1.5f32)); 175 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 176 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 177 | } 178 | 179 | #[test] 180 | fn and_continue_mocked_then_runs_with_modified_args() { 181 | unsafe { 182 | Struct::::val_method:: 183 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3u8), !b, c + 1.))); 184 | } 185 | 186 | assert_eq!("3 false 2.5", Struct(2u8).val_method(true, 1.5f32)); 187 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 188 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 189 | } 190 | 191 | #[test] 192 | fn and_return_mocked_then_returns_mocking_result() { 193 | unsafe { 194 | Struct::::val_method:: 195 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 196 | } 197 | 198 | assert_eq!("mocked 2 true 1.5", Struct(2u8).val_method(true, 1.5f32)); 199 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 200 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool) -> String { 6 | format!("{}", arg) 7 | } 8 | 9 | fn ref_method(&self, arg: bool) -> String { 10 | format!("{} {}", self.to_string(), arg) 11 | } 12 | 13 | fn ref_mut_method(&mut self, arg: bool) -> String { 14 | self.modify(); 15 | format!("{} {}", self.to_string(), arg) 16 | } 17 | 18 | fn val_method(self, arg: bool) -> String { 19 | format!("{} {}", self.to_string(), arg) 20 | } 21 | 22 | fn to_string(&self) -> String; 23 | fn modify(&mut self); 24 | } 25 | 26 | struct Struct(T); 27 | 28 | impl Trait for Struct { 29 | fn to_string(&self) -> String { 30 | self.0.to_string() 31 | } 32 | 33 | fn modify(&mut self) { 34 | self.0 = T::default(); 35 | } 36 | } 37 | 38 | mod and_method_is_static { 39 | use super::*; 40 | 41 | #[test] 42 | fn and_not_mocked_then_runs_normally() { 43 | assert_eq!("true", Struct::::static_method(true)); 44 | assert_eq!("true", Struct::<&str>::static_method(true)); 45 | } 46 | 47 | #[test] 48 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 49 | unsafe { 50 | Struct::::static_method.mock_raw(|a| MockResult::Continue((!a,))); 51 | } 52 | 53 | assert_eq!("false", Struct::::static_method(true)); 54 | assert_eq!("true", Struct::<&str>::static_method(true)); 55 | } 56 | 57 | #[test] 58 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 59 | unsafe { 60 | Struct::::static_method.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 61 | } 62 | 63 | assert_eq!("mocked true", Struct::::static_method(true)); 64 | assert_eq!("true", Struct::<&str>::static_method(true)); 65 | } 66 | } 67 | 68 | mod and_method_is_ref_method { 69 | use super::*; 70 | 71 | #[test] 72 | fn and_not_mocked_then_runs_normally() { 73 | assert_eq!("2 true", Struct(2u8).ref_method(true)); 74 | assert_eq!("abc true", Struct("abc").ref_method(true)); 75 | } 76 | 77 | #[test] 78 | fn and_continue_mocked_then_runs_with_modified_args() { 79 | let struct_2 = Struct(2u8); 80 | let struct_3 = Struct(3u8); 81 | unsafe { 82 | Struct::::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 83 | } 84 | 85 | assert_eq!("3 false", struct_2.ref_method(true)); 86 | assert_eq!(2, struct_2.0); 87 | assert_eq!(3, struct_3.0); 88 | assert_eq!("abc true", Struct("abc").ref_method(true)); 89 | } 90 | 91 | #[test] 92 | fn and_return_mocked_then_returns_mocking_result() { 93 | let struct_2 = Struct(2u8); 94 | unsafe { 95 | Struct::::ref_method 96 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 97 | } 98 | 99 | assert_eq!("mocked 2 true", struct_2.ref_method(true)); 100 | assert_eq!(2, struct_2.0); 101 | assert_eq!("abc true", Struct("abc").ref_method(true)); 102 | } 103 | } 104 | 105 | mod and_method_is_ref_mut_method { 106 | use super::*; 107 | 108 | #[test] 109 | fn and_not_mocked_then_runs_normally() { 110 | let mut struct_2 = Struct(2u8); 111 | let mut struct_str = Struct("str"); 112 | 113 | assert_eq!("0 true", struct_2.ref_mut_method(true)); 114 | assert_eq!(0, struct_2.0); 115 | assert_eq!(" true", struct_str.ref_mut_method(true)); 116 | assert_eq!("", struct_str.0); 117 | } 118 | 119 | #[test] 120 | fn and_continue_mocked_then_runs_with_modified_args() { 121 | let mut struct_2 = Struct(2u8); 122 | let struct_3 = Struct(3u8); 123 | let mut struct_str = Struct("str"); 124 | unsafe { 125 | Struct::::ref_mut_method 126 | .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 127 | } 128 | 129 | assert_eq!("0 false", struct_2.ref_mut_method(true)); 130 | assert_eq!(2, struct_2.0); 131 | assert_eq!(0, struct_3.0); 132 | assert_eq!(" true", struct_str.ref_mut_method(true)); 133 | assert_eq!("", struct_str.0); 134 | } 135 | 136 | #[test] 137 | fn and_return_mocked_then_returns_mocking_result() { 138 | let mut struct_2 = Struct(2u8); 139 | let mut struct_str = Struct("str"); 140 | unsafe { 141 | Struct::::ref_mut_method 142 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 143 | } 144 | 145 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true)); 146 | assert_eq!(2, struct_2.0); 147 | assert_eq!(" true", struct_str.ref_mut_method(true)); 148 | assert_eq!("", struct_str.0); 149 | } 150 | } 151 | 152 | mod and_method_is_val_method { 153 | use super::*; 154 | 155 | #[test] 156 | fn and_not_mocked_then_runs_normally() { 157 | assert_eq!("2 true", Struct(2u8).val_method(true)); 158 | assert_eq!("abc true", Struct("abc").val_method(true)); 159 | } 160 | 161 | #[test] 162 | fn and_continue_mocked_then_runs_with_modified_args() { 163 | unsafe { 164 | Struct::::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3u8), !b))); 165 | } 166 | 167 | assert_eq!("3 false", Struct(2u8).val_method(true)); 168 | assert_eq!("abc true", Struct("abc").val_method(true)); 169 | } 170 | 171 | #[test] 172 | fn and_return_mocked_then_returns_mocking_result() { 173 | unsafe { 174 | Struct::::val_method 175 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 176 | } 177 | 178 | assert_eq!("mocked 2 true", Struct(2u8).val_method(true)); 179 | assert_eq!("abc true", Struct("abc").val_method(true)); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool, method_generic: T) -> String { 6 | format!("{} {}", arg, method_generic) 7 | } 8 | 9 | fn ref_method(&self, arg: bool, method_generic: T) -> String { 10 | format!("{} {} {}", self.to_string(), arg, method_generic) 11 | } 12 | 13 | fn ref_mut_method(&mut self, arg: bool, method_generic: T) -> String { 14 | self.modify(); 15 | format!("{} {} {}", self.to_string(), arg, method_generic) 16 | } 17 | 18 | fn val_method(self, arg: bool, method_generic: T) -> String { 19 | format!("{} {} {}", self.to_string(), arg, method_generic) 20 | } 21 | 22 | fn to_string(&self) -> String; 23 | fn modify(&mut self); 24 | } 25 | 26 | struct Struct(u8); 27 | 28 | impl Trait for Struct { 29 | fn to_string(&self) -> String { 30 | self.0.to_string() 31 | } 32 | 33 | fn modify(&mut self) { 34 | self.0 *= 2; 35 | } 36 | } 37 | 38 | mod and_method_is_static { 39 | use super::*; 40 | 41 | #[test] 42 | fn and_not_mocked_then_runs_normally() { 43 | assert_eq!("true 1.5", Struct::static_method(true, 1.5f32)); 44 | assert_eq!("true abc", Struct::static_method(true, "abc")); 45 | } 46 | 47 | #[test] 48 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 49 | unsafe { 50 | Struct::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 51 | } 52 | 53 | assert_eq!("false 3.5", Struct::static_method(true, 2.5f32)); 54 | assert_eq!("true abc", Struct::static_method(true, "abc")); 55 | } 56 | 57 | #[test] 58 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 59 | unsafe { 60 | Struct::static_method:: 61 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 62 | } 63 | 64 | assert_eq!("mocked true 2.5", Struct::static_method(true, 2.5f32)); 65 | assert_eq!("true abc", Struct::static_method(true, "abc")); 66 | } 67 | } 68 | 69 | mod and_method_is_ref_method { 70 | use super::*; 71 | 72 | #[test] 73 | fn and_not_mocked_then_runs_normally() { 74 | assert_eq!("2 true 1.5", Struct(2).ref_method(true, 1.5f32)); 75 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 76 | } 77 | 78 | #[test] 79 | fn and_continue_mocked_then_runs_with_modified_args() { 80 | let struct_2 = Struct(2); 81 | let struct_3 = Struct(3); 82 | unsafe { 83 | Struct::ref_method:: 84 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 85 | } 86 | 87 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32)); 88 | assert_eq!(2, struct_2.0); 89 | assert_eq!(3, struct_3.0); 90 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 91 | } 92 | 93 | #[test] 94 | fn and_return_mocked_then_returns_mocking_result() { 95 | let struct_2 = Struct(2); 96 | unsafe { 97 | Struct::ref_method:: 98 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 99 | } 100 | 101 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32)); 102 | assert_eq!(2, struct_2.0); 103 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 104 | } 105 | } 106 | 107 | mod and_method_is_ref_mut_method { 108 | use super::*; 109 | 110 | #[test] 111 | fn and_not_mocked_then_runs_normally() { 112 | let mut struct_2 = Struct(2); 113 | let mut struct_4 = Struct(4); 114 | 115 | assert_eq!("4 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 116 | assert_eq!(4, struct_2.0); 117 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 118 | assert_eq!(8, struct_4.0); 119 | } 120 | 121 | #[test] 122 | fn and_continue_mocked_then_runs_with_modified_args() { 123 | let mut struct_2 = Struct(2); 124 | let struct_3 = Struct(3); 125 | let mut struct_4 = Struct(4); 126 | unsafe { 127 | Struct::ref_mut_method:: 128 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 129 | } 130 | 131 | assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); 132 | assert_eq!(2, struct_2.0); 133 | assert_eq!(6, struct_3.0); 134 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 135 | assert_eq!(8, struct_4.0); 136 | } 137 | 138 | #[test] 139 | fn and_return_mocked_then_returns_mocking_result() { 140 | let mut struct_2 = Struct(2); 141 | let mut struct_4 = Struct(4); 142 | unsafe { 143 | Struct::ref_mut_method:: 144 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 145 | } 146 | 147 | assert_eq!("mocked 2 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 148 | assert_eq!(2, struct_2.0); 149 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 150 | assert_eq!(8, struct_4.0); 151 | } 152 | } 153 | 154 | mod and_method_is_val_method { 155 | use super::*; 156 | 157 | #[test] 158 | fn and_not_mocked_then_runs_normally() { 159 | assert_eq!("2 true 1.5", Struct(2).val_method(true, 1.5f32)); 160 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 161 | } 162 | 163 | #[test] 164 | fn and_continue_mocked_then_runs_with_modified_args() { 165 | unsafe { 166 | Struct::val_method:: 167 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3), !b, c + 1.))); 168 | } 169 | 170 | assert_eq!("3 false 2.5", Struct(2).val_method(true, 1.5f32)); 171 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 172 | } 173 | 174 | #[test] 175 | fn and_return_mocked_then_returns_mocking_result() { 176 | unsafe { 177 | Struct::val_method:: 178 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 179 | } 180 | 181 | assert_eq!("mocked 2 true 1.5", Struct(2).val_method(true, 1.5f32)); 182 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[mockable] 4 | trait Trait: Sized { 5 | fn static_method(arg: bool) -> String { 6 | format!("{}", arg) 7 | } 8 | 9 | fn ref_method(&self, arg: bool) -> String { 10 | format!("{} {}", self.to_string(), arg) 11 | } 12 | 13 | fn ref_mut_method(&mut self, arg: bool) -> String { 14 | self.modify(); 15 | format!("{} {}", self.to_string(), arg) 16 | } 17 | 18 | fn val_method(self, arg: bool) -> String { 19 | format!("{} {}", self.to_string(), arg) 20 | } 21 | 22 | fn to_string(&self) -> String; 23 | fn modify(&mut self); 24 | } 25 | 26 | struct Struct(u8); 27 | 28 | impl Trait for Struct { 29 | fn to_string(&self) -> String { 30 | self.0.to_string() 31 | } 32 | 33 | fn modify(&mut self) { 34 | self.0 *= 2; 35 | } 36 | } 37 | 38 | mod and_method_is_static { 39 | use super::*; 40 | 41 | #[test] 42 | fn and_not_mocked_then_runs_normally() { 43 | assert_eq!("true", Struct::static_method(true)); 44 | } 45 | 46 | #[test] 47 | fn and_continue_mocked_then_runs_with_modified_args() { 48 | unsafe { 49 | Struct::static_method.mock_raw(|a| MockResult::Continue((!a,))); 50 | } 51 | 52 | assert_eq!("false", Struct::static_method(true)); 53 | } 54 | 55 | #[test] 56 | fn and_return_mocked_then_returns_mocking_result() { 57 | unsafe { 58 | Struct::static_method.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 59 | } 60 | 61 | assert_eq!("mocked true", Struct::static_method(true)); 62 | } 63 | } 64 | 65 | mod and_method_is_ref_method { 66 | use super::*; 67 | 68 | #[test] 69 | fn and_not_mocked_then_runs_normally() { 70 | assert_eq!("2 true", Struct(2).ref_method(true)); 71 | } 72 | 73 | #[test] 74 | fn and_continue_mocked_then_runs_with_modified_args() { 75 | let struct_2 = Struct(2); 76 | let struct_3 = Struct(3); 77 | unsafe { 78 | Struct::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 79 | } 80 | 81 | assert_eq!("3 false", struct_2.ref_method(true)); 82 | assert_eq!(2, struct_2.0); 83 | assert_eq!(3, struct_3.0); 84 | } 85 | 86 | #[test] 87 | fn and_return_mocked_then_returns_mocking_result() { 88 | let struct_2 = Struct(2); 89 | unsafe { 90 | Struct::ref_method.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 91 | } 92 | 93 | assert_eq!("mocked 2 true", struct_2.ref_method(true)); 94 | assert_eq!(2, struct_2.0); 95 | } 96 | } 97 | 98 | mod and_method_is_ref_mut_method { 99 | use super::*; 100 | 101 | #[test] 102 | fn and_not_mocked_then_runs_normally() { 103 | let mut struct_2 = Struct(2); 104 | 105 | assert_eq!("4 true", struct_2.ref_mut_method(true)); 106 | assert_eq!(4, struct_2.0); 107 | } 108 | 109 | #[test] 110 | fn and_continue_mocked_then_runs_with_modified_args() { 111 | let mut struct_2 = Struct(2); 112 | let struct_3 = Struct(3); 113 | unsafe { 114 | Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 115 | } 116 | 117 | assert_eq!("6 false", struct_2.ref_mut_method(true)); 118 | assert_eq!(2, struct_2.0); 119 | assert_eq!(6, struct_3.0); 120 | } 121 | 122 | #[test] 123 | fn and_return_mocked_then_returns_mocking_result() { 124 | let mut struct_2 = Struct(2); 125 | unsafe { 126 | Struct::ref_mut_method 127 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 128 | } 129 | 130 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true)); 131 | assert_eq!(2, struct_2.0); 132 | } 133 | } 134 | 135 | mod and_method_is_val_method { 136 | use super::*; 137 | 138 | #[test] 139 | fn and_not_mocked_then_runs_normally() { 140 | assert_eq!("2 true", Struct(2).val_method(true)); 141 | } 142 | 143 | #[test] 144 | fn and_continue_mocked_then_runs_with_modified_args() { 145 | unsafe { 146 | Struct::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3), !b))); 147 | } 148 | 149 | assert_eq!("3 false", Struct(2).val_method(true)); 150 | } 151 | 152 | #[test] 153 | fn and_return_mocked_then_returns_mocking_result() { 154 | unsafe { 155 | Struct::val_method.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 156 | } 157 | 158 | assert_eq!("mocked 2 true", Struct(2).val_method(true)); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /tests/mocking_traits/mod.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | mod when_trait_generic_struct_generic_method_generic; 4 | mod when_trait_generic_struct_generic_method_regular; 5 | mod when_trait_generic_struct_regular_method_generic; 6 | mod when_trait_generic_struct_regular_method_regular; 7 | mod when_trait_regular_struct_generic_method_generic; 8 | mod when_trait_regular_struct_generic_method_regular; 9 | mod when_trait_regular_struct_regular_method_generic; 10 | mod when_trait_regular_struct_regular_method_regular; 11 | 12 | mod mocking_impls_of_traits_with_path { 13 | use self::trait_mod::Trait; 14 | use super::*; 15 | 16 | struct Struct(); 17 | 18 | mod trait_mod { 19 | pub trait Trait { 20 | fn method() -> &'static str; 21 | } 22 | } 23 | 24 | #[mockable] 25 | impl self::trait_mod::Trait for Struct { 26 | fn method() -> &'static str { 27 | "not mocked" 28 | } 29 | } 30 | 31 | #[test] 32 | fn mocks_successfully() { 33 | unsafe { 34 | Struct::method.mock_raw(|| MockResult::Return("mocked")); 35 | } 36 | 37 | assert_eq!("mocked", Struct::method()); 38 | } 39 | } 40 | 41 | mod mocking_impls_of_traits_generic_over_generic_refs { 42 | use super::*; 43 | 44 | struct Struct(); 45 | 46 | trait Trait { 47 | fn method() -> &'static str; 48 | } 49 | 50 | #[mockable] 51 | impl Trait<&T> for Struct { 52 | fn method() -> &'static str { 53 | "not mocked" 54 | } 55 | } 56 | 57 | #[test] 58 | fn mocks_successfully() { 59 | unsafe { 60 | >::method.mock_raw(|| MockResult::Return("mocked")); 61 | } 62 | 63 | assert_eq!("mocked", >::method()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_generic_struct_generic_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool, method_generic: U, trait_generic: V) -> String; 5 | fn ref_method(&self, arg: bool, method_generic: U, trait_generic: V) -> String; 6 | fn ref_mut_method( 7 | &mut self, 8 | arg: bool, 9 | method_generic: U, 10 | trait_generic: V, 11 | ) -> String; 12 | fn val_method(self, arg: bool, method_generic: U, trait_generic: V) -> String; 13 | } 14 | 15 | struct Struct(T); 16 | 17 | #[mockable] 18 | impl Trait for Struct { 19 | fn static_method(arg: bool, method_generic: U, trait_generic: V) -> String { 20 | format!("{} {} {}", arg, method_generic, trait_generic) 21 | } 22 | 23 | fn ref_method(&self, arg: bool, method_generic: U, trait_generic: V) -> String { 24 | format!("{} {} {} {}", self.0, arg, method_generic, trait_generic) 25 | } 26 | 27 | fn ref_mut_method( 28 | &mut self, 29 | arg: bool, 30 | method_generic: U, 31 | trait_generic: V, 32 | ) -> String { 33 | self.0 = T::default(); 34 | format!("{} {} {} {}", self.0, arg, method_generic, trait_generic) 35 | } 36 | 37 | fn val_method(self, arg: bool, method_generic: U, trait_generic: V) -> String { 38 | format!("{} {} {} {}", self.0, arg, method_generic, trait_generic) 39 | } 40 | } 41 | 42 | mod and_method_is_static { 43 | use super::*; 44 | 45 | #[test] 46 | fn and_not_mocked_then_runs_normally() { 47 | assert_eq!("true 2.5 a", Struct::::static_method(true, 2.5f32, 'a')); 48 | assert_eq!("true abc a", Struct::::static_method(true, "abc", 'a')); 49 | assert_eq!( 50 | "true 2.5 a", 51 | Struct::<&str>::static_method(true, 2.5f32, 'a') 52 | ); 53 | assert_eq!( 54 | "true 2.5 abc", 55 | Struct::::static_method(true, 2.5f32, "abc") 56 | ); 57 | } 58 | 59 | #[test] 60 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 61 | unsafe { 62 | as Trait>::static_method:: 63 | .mock_raw(|a, b, c| MockResult::Continue((!a, b + 1., c.to_ascii_uppercase()))); 64 | } 65 | 66 | assert_eq!( 67 | "false 3.5 A", 68 | Struct::::static_method(true, 2.5f32, 'a') 69 | ); 70 | assert_eq!("true abc a", Struct::::static_method(true, "abc", 'a')); 71 | assert_eq!( 72 | "true 2.5 a", 73 | Struct::<&str>::static_method(true, 2.5f32, 'a') 74 | ); 75 | assert_eq!( 76 | "true 2.5 abc", 77 | Struct::::static_method(true, 2.5f32, "abc") 78 | ); 79 | } 80 | 81 | #[test] 82 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 83 | unsafe { 84 | as Trait>::static_method:: 85 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a, b, c))); 86 | } 87 | 88 | assert_eq!( 89 | "mocked true 2.5 a", 90 | Struct::::static_method(true, 2.5f32, 'a') 91 | ); 92 | assert_eq!("true abc a", Struct::::static_method(true, "abc", 'a')); 93 | assert_eq!( 94 | "true 2.5 a", 95 | Struct::<&str>::static_method(true, 2.5f32, 'a') 96 | ); 97 | assert_eq!( 98 | "true 2.5 abc", 99 | Struct::::static_method(true, 2.5f32, "abc") 100 | ); 101 | } 102 | } 103 | 104 | mod and_method_is_ref_method { 105 | use super::*; 106 | 107 | #[test] 108 | fn and_not_mocked_then_runs_normally() { 109 | assert_eq!("2 true 1.5 a", Struct(2u8).ref_method(true, 1.5f32, 'a')); 110 | assert_eq!("2 true abc a", Struct(2u8).ref_method(true, "abc", 'a')); 111 | assert_eq!( 112 | "abc true 1.5 a", 113 | Struct("abc").ref_method(true, 1.5f32, 'a') 114 | ); 115 | assert_eq!( 116 | "2 true 1.5 abc", 117 | Struct(2u8).ref_method(true, 1.5f32, "abc") 118 | ); 119 | } 120 | 121 | #[test] 122 | fn and_continue_mocked_then_runs_with_modified_args() { 123 | let struct_2 = Struct(2u8); 124 | let struct_3 = Struct(3u8); 125 | unsafe { 126 | as Trait>::ref_method::.mock_raw(|_, b, c, d| { 127 | MockResult::Continue((&struct_3, !b, c + 1., d.to_ascii_uppercase())) 128 | }); 129 | } 130 | 131 | assert_eq!("3 false 2.5 A", struct_2.ref_method(true, 1.5f32, 'a')); 132 | assert_eq!(2, struct_2.0); 133 | assert_eq!(3, struct_3.0); 134 | assert_eq!("2 true abc a", Struct(2u8).ref_method(true, "abc", 'a')); 135 | assert_eq!( 136 | "abc true 1.5 a", 137 | Struct("abc").ref_method(true, 1.5f32, 'a') 138 | ); 139 | assert_eq!( 140 | "2 true 1.5 abc", 141 | Struct(2u8).ref_method(true, 1.5f32, "abc") 142 | ); 143 | } 144 | 145 | #[test] 146 | fn and_return_mocked_then_returns_mocking_result() { 147 | let struct_2 = Struct(2u8); 148 | unsafe { 149 | as Trait>::ref_method::.mock_raw(|a, b, c, d| { 150 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 151 | }); 152 | } 153 | 154 | assert_eq!( 155 | "mocked 2 true 1.5 a", 156 | struct_2.ref_method(true, 1.5f32, 'a') 157 | ); 158 | assert_eq!(2, struct_2.0); 159 | assert_eq!("2 true abc a", Struct(2u8).ref_method(true, "abc", 'a')); 160 | assert_eq!( 161 | "abc true 1.5 a", 162 | Struct("abc").ref_method(true, 1.5f32, 'a') 163 | ); 164 | assert_eq!( 165 | "2 true 1.5 abc", 166 | Struct(2u8).ref_method(true, 1.5f32, "abc") 167 | ); 168 | } 169 | } 170 | 171 | mod and_method_is_ref_mut_method { 172 | use super::*; 173 | 174 | #[test] 175 | fn and_not_mocked_then_runs_normally() { 176 | let mut struct_2 = Struct(2u8); 177 | let mut struct_4 = Struct(4u8); 178 | let mut struct_str = Struct("abc"); 179 | let mut struct_5 = Struct(5u8); 180 | 181 | assert_eq!("0 true 1.5 a", struct_2.ref_mut_method(true, 1.5f32, 'a')); 182 | assert_eq!(0, struct_2.0); 183 | assert_eq!("0 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 184 | assert_eq!(0, struct_4.0); 185 | assert_eq!(" true 1.5 a", struct_str.ref_mut_method(true, 1.5, 'a')); 186 | assert_eq!("", struct_str.0); 187 | assert_eq!( 188 | "0 true 1.5 abc", 189 | struct_5.ref_mut_method(true, 1.5f32, "abc") 190 | ); 191 | assert_eq!(0, struct_5.0); 192 | } 193 | 194 | #[test] 195 | fn and_continue_mocked_then_runs_with_modified_args() { 196 | let mut struct_2 = Struct(2u8); 197 | let struct_3 = Struct(3u8); 198 | let mut struct_4 = Struct(4u8); 199 | let mut struct_str = Struct("abc"); 200 | let mut struct_5 = Struct(5u8); 201 | unsafe { 202 | as Trait>::ref_mut_method::.mock_raw(|_, b, c, d| { 203 | MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) 204 | }); 205 | } 206 | 207 | assert_eq!("0 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); 208 | assert_eq!(2, struct_2.0); 209 | assert_eq!(0, struct_3.0); 210 | assert_eq!("0 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 211 | assert_eq!(0, struct_4.0); 212 | assert_eq!(" true 1.5 a", struct_str.ref_mut_method(true, 1.5, 'a')); 213 | assert_eq!("", struct_str.0); 214 | assert_eq!( 215 | "0 true 1.5 abc", 216 | struct_5.ref_mut_method(true, 1.5f32, "abc") 217 | ); 218 | assert_eq!(0, struct_5.0); 219 | } 220 | 221 | #[test] 222 | fn and_return_mocked_then_returns_mocking_result() { 223 | let mut struct_2 = Struct(2u8); 224 | let mut struct_4 = Struct(4u8); 225 | let mut struct_str = Struct("abc"); 226 | let mut struct_5 = Struct(5u8); 227 | unsafe { 228 | as Trait>::ref_mut_method::.mock_raw(|a, b, c, d| { 229 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 230 | }); 231 | } 232 | 233 | assert_eq!( 234 | "mocked 2 true 1.5 a", 235 | struct_2.ref_mut_method(true, 1.5f32, 'a') 236 | ); 237 | assert_eq!(2, struct_2.0); 238 | assert_eq!("0 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 239 | assert_eq!(0, struct_4.0); 240 | assert_eq!(" true 1.5 a", struct_str.ref_mut_method(true, 1.5, 'a')); 241 | assert_eq!("", struct_str.0); 242 | assert_eq!( 243 | "0 true 1.5 abc", 244 | struct_5.ref_mut_method(true, 1.5f32, "abc") 245 | ); 246 | assert_eq!(0, struct_5.0); 247 | } 248 | } 249 | 250 | mod and_method_is_val_method { 251 | use super::*; 252 | 253 | #[test] 254 | fn and_not_mocked_then_runs_normally() { 255 | assert_eq!("2 true 1.5 a", Struct(2u8).val_method(true, 1.5f32, 'a')); 256 | assert_eq!("2 true abc a", Struct(2u8).val_method(true, "abc", 'a')); 257 | assert_eq!( 258 | "abc true 1.5 a", 259 | Struct("abc").val_method(true, 1.5f32, 'a') 260 | ); 261 | assert_eq!( 262 | "2 true 1.5 abc", 263 | Struct(2u8).val_method(true, 1.5f32, "abc") 264 | ); 265 | } 266 | 267 | #[test] 268 | fn and_continue_mocked_then_runs_with_modified_args() { 269 | unsafe { 270 | as Trait>::val_method::.mock_raw(move |_, b, c, d| { 271 | MockResult::Continue((Struct(3u8), !b, c + 1., d.to_ascii_uppercase())) 272 | }); 273 | } 274 | 275 | assert_eq!("3 false 2.5 A", Struct(2u8).val_method(true, 1.5f32, 'a')); 276 | assert_eq!("2 true abc a", Struct(2u8).val_method(true, "abc", 'a')); 277 | assert_eq!( 278 | "abc true 1.5 a", 279 | Struct("abc").val_method(true, 1.5f32, 'a') 280 | ); 281 | assert_eq!( 282 | "2 true 1.5 abc", 283 | Struct(2u8).val_method(true, 1.5f32, "abc") 284 | ); 285 | } 286 | 287 | #[test] 288 | fn and_return_mocked_then_returns_mocking_result() { 289 | unsafe { 290 | as Trait>::val_method::.mock_raw(|a, b, c, d| { 291 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 292 | }); 293 | } 294 | 295 | assert_eq!( 296 | "mocked 2 true 1.5 a", 297 | Struct(2u8).val_method(true, 1.5f32, 'a') 298 | ); 299 | assert_eq!("2 true abc a", Struct(2u8).val_method(true, "abc", 'a')); 300 | assert_eq!( 301 | "abc true 1.5 a", 302 | Struct("abc").val_method(true, 1.5f32, 'a') 303 | ); 304 | assert_eq!( 305 | "2 true 1.5 abc", 306 | Struct(2u8).val_method(true, 1.5f32, "abc") 307 | ); 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_generic_struct_generic_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool, trait_generic: V) -> String; 5 | fn ref_method(&self, arg: bool, trait_generic: V) -> String; 6 | fn ref_mut_method(&mut self, arg: bool, trait_generic: V) -> String; 7 | fn val_method(self, arg: bool, trait_generic: V) -> String; 8 | } 9 | 10 | struct Struct(T); 11 | 12 | #[mockable] 13 | impl Trait for Struct { 14 | fn static_method(arg: bool, trait_generic: V) -> String { 15 | format!("{} {}", arg, trait_generic) 16 | } 17 | 18 | fn ref_method(&self, arg: bool, trait_generic: V) -> String { 19 | format!("{} {} {}", self.0, arg, trait_generic) 20 | } 21 | 22 | fn ref_mut_method(&mut self, arg: bool, trait_generic: V) -> String { 23 | self.0 = T::default(); 24 | format!("{} {} {}", self.0, arg, trait_generic) 25 | } 26 | 27 | fn val_method(self, arg: bool, trait_generic: V) -> String { 28 | format!("{} {} {}", self.0, arg, trait_generic) 29 | } 30 | } 31 | 32 | mod and_method_is_static { 33 | use super::*; 34 | 35 | #[test] 36 | fn and_not_mocked_then_runs_normally() { 37 | assert_eq!("true a", Struct::::static_method(true, 'a')); 38 | assert_eq!("true a", Struct::<&str>::static_method(true, 'a')); 39 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 40 | } 41 | 42 | #[test] 43 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 44 | unsafe { 45 | as Trait>::static_method 46 | .mock_raw(|a, b| MockResult::Continue((!a, b.to_ascii_uppercase()))); 47 | } 48 | 49 | assert_eq!("false A", Struct::::static_method(true, 'a')); 50 | assert_eq!("true a", Struct::<&str>::static_method(true, 'a')); 51 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 52 | } 53 | 54 | #[test] 55 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 56 | unsafe { 57 | as Trait>::static_method 58 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 59 | } 60 | 61 | assert_eq!("mocked true a", Struct::::static_method(true, 'a')); 62 | assert_eq!("true a", Struct::<&str>::static_method(true, 'a')); 63 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 64 | } 65 | } 66 | 67 | mod and_method_is_ref_method { 68 | use super::*; 69 | 70 | #[test] 71 | fn and_not_mocked_then_runs_normally() { 72 | assert_eq!("2 true a", Struct(2u8).ref_method(true, 'a')); 73 | assert_eq!("abc true a", Struct("abc").ref_method(true, 'a')); 74 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 75 | } 76 | 77 | #[test] 78 | fn and_continue_mocked_then_runs_with_modified_args() { 79 | let struct_2 = Struct(2u8); 80 | let struct_3 = Struct(3u8); 81 | unsafe { 82 | as Trait>::ref_method 83 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c.to_ascii_uppercase()))); 84 | } 85 | 86 | assert_eq!("3 false A", struct_2.ref_method(true, 'a')); 87 | assert_eq!(2, struct_2.0); 88 | assert_eq!(3, struct_3.0); 89 | assert_eq!("abc true a", Struct("abc").ref_method(true, 'a')); 90 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 91 | } 92 | 93 | #[test] 94 | fn and_return_mocked_then_returns_mocking_result() { 95 | let struct_2 = Struct(2u8); 96 | unsafe { 97 | as Trait>::ref_method 98 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 99 | } 100 | 101 | assert_eq!("mocked 2 true a", struct_2.ref_method(true, 'a')); 102 | assert_eq!(2, struct_2.0); 103 | assert_eq!("abc true a", Struct("abc").ref_method(true, 'a')); 104 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 105 | } 106 | } 107 | 108 | mod and_method_is_ref_mut_method { 109 | use super::*; 110 | 111 | #[test] 112 | fn and_not_mocked_then_runs_normally() { 113 | let mut struct_2 = Struct(2u8); 114 | let mut struct_str = Struct("str"); 115 | let mut struct_4 = Struct(4u8); 116 | 117 | assert_eq!("0 true a", struct_2.ref_mut_method(true, 'a')); 118 | assert_eq!(0, struct_2.0); 119 | assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); 120 | assert_eq!("", struct_str.0); 121 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 122 | assert_eq!(0, struct_4.0); 123 | } 124 | 125 | #[test] 126 | fn and_continue_mocked_then_runs_with_modified_args() { 127 | let mut struct_2 = Struct(2u8); 128 | let struct_3 = Struct(3u8); 129 | let mut struct_str = Struct("str"); 130 | let mut struct_4 = Struct(4u8); 131 | unsafe { 132 | as Trait>::ref_mut_method.mock_raw(|_, b, c| { 133 | MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) 134 | }); 135 | } 136 | 137 | assert_eq!("0 false A", struct_2.ref_mut_method(true, 'a')); 138 | assert_eq!(2, struct_2.0); 139 | assert_eq!(0, struct_3.0); 140 | assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); 141 | assert_eq!("", struct_str.0); 142 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 143 | assert_eq!(0, struct_4.0); 144 | } 145 | 146 | #[test] 147 | fn and_return_mocked_then_returns_mocking_result() { 148 | let mut struct_2 = Struct(2u8); 149 | let mut struct_str = Struct("str"); 150 | let mut struct_4 = Struct(4u8); 151 | unsafe { 152 | as Trait>::ref_mut_method 153 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 154 | } 155 | 156 | assert_eq!("mocked 2 true a", struct_2.ref_mut_method(true, 'a')); 157 | assert_eq!(2, struct_2.0); 158 | assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); 159 | assert_eq!("", struct_str.0); 160 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 161 | assert_eq!(0, struct_4.0); 162 | } 163 | } 164 | 165 | mod and_method_is_val_method { 166 | use super::*; 167 | 168 | #[test] 169 | fn and_not_mocked_then_runs_normally() { 170 | assert_eq!("2 true a", Struct(2u8).val_method(true, 'a')); 171 | assert_eq!("abc true a", Struct("abc").val_method(true, 'a')); 172 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 173 | } 174 | 175 | #[test] 176 | fn and_continue_mocked_then_runs_with_modified_args() { 177 | unsafe { 178 | as Trait>::val_method.mock_raw(move |_, b, c| { 179 | MockResult::Continue((Struct(3u8), !b, c.to_ascii_uppercase())) 180 | }); 181 | } 182 | 183 | assert_eq!("3 false A", Struct(2u8).val_method(true, 'a')); 184 | assert_eq!("abc true a", Struct("abc").val_method(true, 'a')); 185 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 186 | } 187 | 188 | #[test] 189 | fn and_return_mocked_then_returns_mocking_result() { 190 | unsafe { 191 | as Trait>::val_method 192 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 193 | } 194 | 195 | assert_eq!("mocked 2 true a", Struct(2u8).val_method(true, 'a')); 196 | assert_eq!("abc true a", Struct("abc").val_method(true, 'a')); 197 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_generic_struct_regular_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool, method_generic: T, trait_generic: V) -> String; 5 | fn ref_method(&self, arg: bool, method_generic: T, trait_generic: V) -> String; 6 | fn ref_mut_method( 7 | &mut self, 8 | arg: bool, 9 | method_generic: T, 10 | trait_generic: V, 11 | ) -> String; 12 | fn val_method(self, arg: bool, method_generic: T, trait_generic: V) -> String; 13 | } 14 | 15 | struct Struct(u8); 16 | 17 | #[mockable] 18 | impl Trait for Struct { 19 | fn static_method(arg: bool, method_generic: T, trait_generic: V) -> String { 20 | format!("{} {} {}", arg, method_generic, trait_generic) 21 | } 22 | 23 | fn ref_method(&self, arg: bool, method_generic: T, trait_generic: V) -> String { 24 | format!("{} {} {} {}", self.0, arg, method_generic, trait_generic) 25 | } 26 | 27 | fn ref_mut_method( 28 | &mut self, 29 | arg: bool, 30 | method_generic: T, 31 | trait_generic: V, 32 | ) -> String { 33 | self.0 *= 2; 34 | format!("{} {} {} {}", self.0, arg, method_generic, trait_generic) 35 | } 36 | 37 | fn val_method(self, arg: bool, method_generic: T, trait_generic: V) -> String { 38 | format!("{} {} {} {}", self.0, arg, method_generic, trait_generic) 39 | } 40 | } 41 | 42 | mod and_method_is_static { 43 | use super::*; 44 | 45 | #[test] 46 | fn and_not_mocked_then_runs_normally() { 47 | assert_eq!("true 1.5 a", Struct::static_method(true, 1.5f32, 'a')); 48 | assert_eq!("true abc a", Struct::static_method(true, "abc", 'a')); 49 | assert_eq!("true 1.5 abc", Struct::static_method(true, 1.5f32, "abc")); 50 | } 51 | 52 | #[test] 53 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 54 | unsafe { 55 | >::static_method:: 56 | .mock_raw(|a, b, c| MockResult::Continue((!a, b + 1., c.to_ascii_uppercase()))); 57 | } 58 | 59 | assert_eq!("false 3.5 A", Struct::static_method(true, 2.5f32, 'a')); 60 | assert_eq!("true abc a", Struct::static_method(true, "abc", 'a')); 61 | assert_eq!("true 1.5 abc", Struct::static_method(true, 1.5f32, "abc")); 62 | } 63 | 64 | #[test] 65 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 66 | unsafe { 67 | >::static_method:: 68 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a, b, c))); 69 | } 70 | 71 | assert_eq!( 72 | "mocked true 2.5 a", 73 | Struct::static_method(true, 2.5f32, 'a') 74 | ); 75 | assert_eq!("true abc a", Struct::static_method(true, "abc", 'a')); 76 | assert_eq!("true 1.5 abc", Struct::static_method(true, 1.5f32, "abc")); 77 | } 78 | } 79 | 80 | mod and_method_is_ref_method { 81 | use super::*; 82 | 83 | #[test] 84 | fn and_not_mocked_then_runs_normally() { 85 | assert_eq!("2 true 1.5 a", Struct(2).ref_method(true, 1.5f32, 'a')); 86 | assert_eq!("2 true abc a", Struct(2).ref_method(true, "abc", 'a')); 87 | assert_eq!("2 true 1.5 abc", Struct(2).ref_method(true, 1.5f32, "abc")); 88 | } 89 | 90 | #[test] 91 | fn and_continue_mocked_then_runs_with_modified_args() { 92 | let struct_2 = Struct(2); 93 | let struct_3 = Struct(3); 94 | unsafe { 95 | >::ref_method::.mock_raw(|_, b, c, d| { 96 | MockResult::Continue((&struct_3, !b, c + 1., d.to_ascii_uppercase())) 97 | }); 98 | } 99 | 100 | assert_eq!("3 false 2.5 A", struct_2.ref_method(true, 1.5f32, 'a')); 101 | assert_eq!(2, struct_2.0); 102 | assert_eq!(3, struct_3.0); 103 | assert_eq!("2 true abc a", Struct(2).ref_method(true, "abc", 'a')); 104 | assert_eq!("2 true 1.5 abc", Struct(2).ref_method(true, 1.5f32, "abc")); 105 | } 106 | 107 | #[test] 108 | fn and_return_mocked_then_returns_mocking_result() { 109 | let struct_2 = Struct(2); 110 | unsafe { 111 | >::ref_method::.mock_raw(|a, b, c, d| { 112 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 113 | }); 114 | } 115 | 116 | assert_eq!( 117 | "mocked 2 true 1.5 a", 118 | struct_2.ref_method(true, 1.5f32, 'a') 119 | ); 120 | assert_eq!(2, struct_2.0); 121 | assert_eq!("2 true abc a", Struct(2).ref_method(true, "abc", 'a')); 122 | assert_eq!("2 true 1.5 abc", Struct(2).ref_method(true, 1.5f32, "abc")); 123 | } 124 | } 125 | 126 | mod and_method_is_ref_mut_method { 127 | use super::*; 128 | 129 | #[test] 130 | fn and_not_mocked_then_runs_normally() { 131 | let mut struct_2 = Struct(2); 132 | let mut struct_4 = Struct(4); 133 | let mut struct_5 = Struct(5); 134 | 135 | assert_eq!("4 true 1.5 a", struct_2.ref_mut_method(true, 1.5f32, 'a')); 136 | assert_eq!(4, struct_2.0); 137 | assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 138 | assert_eq!(8, struct_4.0); 139 | assert_eq!( 140 | "10 true 1.5 abc", 141 | struct_5.ref_mut_method(true, 1.5f32, "abc") 142 | ); 143 | assert_eq!(10, struct_5.0); 144 | } 145 | 146 | #[test] 147 | fn and_continue_mocked_then_runs_with_modified_args() { 148 | let mut struct_2 = Struct(2); 149 | let struct_3 = Struct(3); 150 | let mut struct_4 = Struct(4); 151 | let mut struct_5 = Struct(5); 152 | unsafe { 153 | >::ref_mut_method::.mock_raw(|_, b, c, d| { 154 | MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) 155 | }); 156 | } 157 | 158 | assert_eq!("6 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); 159 | assert_eq!(2, struct_2.0); 160 | assert_eq!(6, struct_3.0); 161 | assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 162 | assert_eq!(8, struct_4.0); 163 | assert_eq!( 164 | "10 true 1.5 abc", 165 | struct_5.ref_mut_method(true, 1.5f32, "abc") 166 | ); 167 | assert_eq!(10, struct_5.0); 168 | } 169 | 170 | #[test] 171 | fn and_return_mocked_then_returns_mocking_result() { 172 | let mut struct_2 = Struct(2); 173 | let mut struct_4 = Struct(4); 174 | let mut struct_5 = Struct(5); 175 | unsafe { 176 | >::ref_mut_method::.mock_raw(|a, b, c, d| { 177 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 178 | }); 179 | } 180 | 181 | assert_eq!( 182 | "mocked 2 true 1.5 a", 183 | struct_2.ref_mut_method(true, 1.5f32, 'a') 184 | ); 185 | assert_eq!(2, struct_2.0); 186 | assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); 187 | assert_eq!(8, struct_4.0); 188 | assert_eq!( 189 | "10 true 1.5 abc", 190 | struct_5.ref_mut_method(true, 1.5f32, "abc") 191 | ); 192 | assert_eq!(10, struct_5.0); 193 | } 194 | } 195 | 196 | mod and_method_is_val_method { 197 | use super::*; 198 | 199 | #[test] 200 | fn and_not_mocked_then_runs_normally() { 201 | assert_eq!("2 true 1.5 a", Struct(2).val_method(true, 1.5f32, 'a')); 202 | assert_eq!("2 true abc a", Struct(2).val_method(true, "abc", 'a')); 203 | assert_eq!("2 true 1.5 abc", Struct(2).val_method(true, 1.5f32, "abc")); 204 | } 205 | 206 | #[test] 207 | fn and_continue_mocked_then_runs_with_modified_args() { 208 | unsafe { 209 | >::val_method::.mock_raw(move |_, b, c, d| { 210 | MockResult::Continue((Struct(3), !b, c + 1., d.to_ascii_uppercase())) 211 | }); 212 | } 213 | 214 | assert_eq!("3 false 2.5 A", Struct(2).val_method(true, 1.5f32, 'a')); 215 | assert_eq!("2 true abc a", Struct(2).val_method(true, "abc", 'a')); 216 | assert_eq!("2 true 1.5 abc", Struct(2).val_method(true, 1.5f32, "abc")); 217 | } 218 | 219 | #[test] 220 | fn and_return_mocked_then_returns_mocking_result() { 221 | unsafe { 222 | >::val_method::.mock_raw(|a, b, c, d| { 223 | MockResult::Return(format!("mocked {} {} {} {}", a.0, b, c, d)) 224 | }); 225 | } 226 | 227 | assert_eq!( 228 | "mocked 2 true 1.5 a", 229 | Struct(2).val_method(true, 1.5f32, 'a') 230 | ); 231 | assert_eq!("2 true abc a", Struct(2).val_method(true, "abc", 'a')); 232 | assert_eq!("2 true 1.5 abc", Struct(2).val_method(true, 1.5f32, "abc")); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_generic_struct_regular_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool, trait_generic: V) -> String; 5 | fn ref_method(&self, arg: bool, trait_generic: V) -> String; 6 | fn ref_mut_method(&mut self, arg: bool, trait_generic: V) -> String; 7 | fn val_method(self, arg: bool, trait_generic: V) -> String; 8 | } 9 | 10 | struct Struct(u8); 11 | 12 | #[mockable] 13 | impl Trait for Struct { 14 | fn static_method(arg: bool, trait_generic: V) -> String { 15 | format!("{} {}", arg, trait_generic) 16 | } 17 | 18 | fn ref_method(&self, arg: bool, trait_generic: V) -> String { 19 | format!("{} {} {}", self.0, arg, trait_generic) 20 | } 21 | 22 | fn ref_mut_method(&mut self, arg: bool, trait_generic: V) -> String { 23 | self.0 *= 2; 24 | format!("{} {} {}", self.0, arg, trait_generic) 25 | } 26 | 27 | fn val_method(self, arg: bool, trait_generic: V) -> String { 28 | format!("{} {} {}", self.0, arg, trait_generic) 29 | } 30 | } 31 | 32 | mod and_method_is_static { 33 | use super::*; 34 | 35 | #[test] 36 | fn and_not_mocked_then_runs_normally() { 37 | assert_eq!("true a", Struct::static_method(true, 'a')); 38 | assert_eq!("true abc", Struct::static_method(true, "abc")); 39 | } 40 | 41 | #[test] 42 | fn and_continue_mocked_then_runs_with_modified_args() { 43 | unsafe { 44 | >::static_method 45 | .mock_raw(|a, b| MockResult::Continue((!a, b.to_ascii_uppercase()))); 46 | } 47 | 48 | assert_eq!("false A", Struct::static_method(true, 'a')); 49 | assert_eq!("true abc", Struct::static_method(true, "abc")); 50 | } 51 | 52 | #[test] 53 | fn and_return_mocked_then_returns_mocking_result() { 54 | unsafe { 55 | >::static_method 56 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 57 | } 58 | 59 | assert_eq!("mocked true a", Struct::static_method(true, 'a')); 60 | assert_eq!("true abc", Struct::static_method(true, "abc")); 61 | } 62 | } 63 | 64 | mod and_method_is_ref_method { 65 | use super::*; 66 | 67 | #[test] 68 | fn and_not_mocked_then_runs_normally() { 69 | assert_eq!("2 true a", Struct(2).ref_method(true, 'a')); 70 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 71 | } 72 | 73 | #[test] 74 | fn and_continue_mocked_then_runs_with_modified_args() { 75 | let struct_2 = Struct(2); 76 | let struct_3 = Struct(3); 77 | unsafe { 78 | >::ref_method 79 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c.to_ascii_uppercase()))); 80 | } 81 | 82 | assert_eq!("3 false A", struct_2.ref_method(true, 'a')); 83 | assert_eq!(2, struct_2.0); 84 | assert_eq!(3, struct_3.0); 85 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 86 | } 87 | 88 | #[test] 89 | fn and_return_mocked_then_returns_mocking_result() { 90 | let struct_2 = Struct(2); 91 | unsafe { 92 | >::ref_method 93 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 94 | } 95 | 96 | assert_eq!("mocked 2 true a", struct_2.ref_method(true, 'a')); 97 | assert_eq!(2, struct_2.0); 98 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 99 | } 100 | } 101 | 102 | mod and_method_is_ref_mut_method { 103 | use super::*; 104 | 105 | #[test] 106 | fn and_not_mocked_then_runs_normally() { 107 | let mut struct_2 = Struct(2); 108 | let mut struct_4 = Struct(4); 109 | 110 | assert_eq!("4 true a", struct_2.ref_mut_method(true, 'a')); 111 | assert_eq!(4, struct_2.0); 112 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 113 | assert_eq!(8, struct_4.0); 114 | } 115 | 116 | #[test] 117 | fn and_continue_mocked_then_runs_with_modified_args() { 118 | let mut struct_2 = Struct(2); 119 | let struct_3 = Struct(3); 120 | let mut struct_4 = Struct(4); 121 | unsafe { 122 | >::ref_mut_method.mock_raw(|_, b, c| { 123 | MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) 124 | }); 125 | } 126 | 127 | assert_eq!("6 false A", struct_2.ref_mut_method(true, 'a')); 128 | assert_eq!(2, struct_2.0); 129 | assert_eq!(6, struct_3.0); 130 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 131 | assert_eq!(8, struct_4.0); 132 | } 133 | 134 | #[test] 135 | fn and_return_mocked_then_returns_mocking_result() { 136 | let mut struct_2 = Struct(2); 137 | let mut struct_4 = Struct(4); 138 | unsafe { 139 | >::ref_mut_method 140 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 141 | } 142 | 143 | assert_eq!("mocked 2 true a", struct_2.ref_mut_method(true, 'a')); 144 | assert_eq!(2, struct_2.0); 145 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 146 | assert_eq!(8, struct_4.0); 147 | } 148 | } 149 | 150 | mod and_method_is_val_method { 151 | use super::*; 152 | 153 | #[test] 154 | fn and_not_mocked_then_runs_normally() { 155 | assert_eq!("2 true a", Struct(2).val_method(true, 'a')); 156 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 157 | } 158 | 159 | #[test] 160 | fn and_continue_mocked_then_runs_with_modified_args() { 161 | unsafe { 162 | >::val_method.mock_raw(move |_, b, c| { 163 | MockResult::Continue((Struct(3), !b, c.to_ascii_uppercase())) 164 | }); 165 | } 166 | 167 | assert_eq!("3 false A", Struct(2).val_method(true, 'a')); 168 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 169 | } 170 | 171 | #[test] 172 | fn and_return_mocked_then_returns_mocking_result() { 173 | unsafe { 174 | >::val_method 175 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 176 | } 177 | 178 | assert_eq!("mocked 2 true a", Struct(2).val_method(true, 'a')); 179 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_regular_struct_generic_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool, method_generic: U) -> String; 5 | fn ref_method(&self, arg: bool, method_generic: U) -> String; 6 | fn ref_mut_method(&mut self, arg: bool, method_generic: U) -> String; 7 | fn val_method(self, arg: bool, method_generic: U) -> String; 8 | } 9 | 10 | struct Struct(T); 11 | 12 | #[mockable] 13 | impl Trait for Struct { 14 | fn static_method(arg: bool, method_generic: U) -> String { 15 | format!("{} {}", arg, method_generic) 16 | } 17 | 18 | fn ref_method(&self, arg: bool, method_generic: U) -> String { 19 | format!("{} {} {}", self.0, arg, method_generic) 20 | } 21 | 22 | fn ref_mut_method(&mut self, arg: bool, method_generic: U) -> String { 23 | self.0 = T::default(); 24 | format!("{} {} {}", self.0, arg, method_generic) 25 | } 26 | 27 | fn val_method(self, arg: bool, method_generic: U) -> String { 28 | format!("{} {} {}", self.0, arg, method_generic) 29 | } 30 | } 31 | 32 | mod and_method_is_static { 33 | use super::*; 34 | 35 | #[test] 36 | fn and_not_mocked_then_runs_normally() { 37 | assert_eq!("true 2.5", Struct::::static_method(true, 2.5f32)); 38 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 39 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 40 | } 41 | 42 | #[test] 43 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 44 | unsafe { 45 | Struct::::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 46 | } 47 | 48 | assert_eq!("false 3.5", Struct::::static_method(true, 2.5f32)); 49 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 50 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 51 | } 52 | 53 | #[test] 54 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 55 | unsafe { 56 | Struct::::static_method:: 57 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 58 | } 59 | 60 | assert_eq!("mocked true 2.5", Struct::::static_method(true, 2.5f32)); 61 | assert_eq!("true abc", Struct::::static_method(true, "abc")); 62 | assert_eq!("true 2.5", Struct::<&str>::static_method(true, 2.5f32)); 63 | } 64 | } 65 | 66 | mod and_method_is_ref_method { 67 | use super::*; 68 | 69 | #[test] 70 | fn and_not_mocked_then_runs_normally() { 71 | assert_eq!("2 true 1.5", Struct(2u8).ref_method(true, 1.5f32)); 72 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 73 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 74 | } 75 | 76 | #[test] 77 | fn and_continue_mocked_then_runs_with_modified_args() { 78 | let struct_2 = Struct(2u8); 79 | let struct_3 = Struct(3u8); 80 | unsafe { 81 | Struct::::ref_method:: 82 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 83 | } 84 | 85 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32)); 86 | assert_eq!(2, struct_2.0); 87 | assert_eq!(3, struct_3.0); 88 | assert_eq!("2 true abc", Struct(2u8).ref_method(true, "abc")); 89 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 90 | } 91 | 92 | #[test] 93 | fn and_return_mocked_then_returns_mocking_result() { 94 | let struct_2 = Struct(2u8); 95 | unsafe { 96 | Struct::::ref_method:: 97 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 98 | } 99 | 100 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32)); 101 | assert_eq!(2, struct_2.0); 102 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 103 | assert_eq!("abc true 1.5", Struct("abc").ref_method(true, 1.5f32)); 104 | } 105 | } 106 | 107 | mod and_method_is_ref_mut_method { 108 | use super::*; 109 | 110 | #[test] 111 | fn and_not_mocked_then_runs_normally() { 112 | let mut struct_2 = Struct(2u8); 113 | let mut struct_4 = Struct(4u8); 114 | let mut struct_str = Struct("abc"); 115 | 116 | assert_eq!("0 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 117 | assert_eq!(0, struct_2.0); 118 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 119 | assert_eq!(0, struct_4.0); 120 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 121 | assert_eq!("", struct_str.0); 122 | } 123 | 124 | #[test] 125 | fn and_continue_mocked_then_runs_with_modified_args() { 126 | let mut struct_2 = Struct(2u8); 127 | let struct_3 = Struct(3u8); 128 | let mut struct_4 = Struct(4u8); 129 | let mut struct_str = Struct("abc"); 130 | unsafe { 131 | Struct::::ref_mut_method:: 132 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 133 | } 134 | 135 | assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); 136 | assert_eq!(2, struct_2.0); 137 | assert_eq!(0, struct_3.0); 138 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 139 | assert_eq!(0, struct_4.0); 140 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 141 | assert_eq!("", struct_str.0); 142 | } 143 | 144 | #[test] 145 | fn and_return_mocked_then_returns_mocking_result() { 146 | let mut struct_2 = Struct(2u8); 147 | let mut struct_4 = Struct(4u8); 148 | let mut struct_str = Struct("abc"); 149 | unsafe { 150 | Struct::::ref_mut_method:: 151 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 152 | } 153 | 154 | assert_eq!("mocked 2 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 155 | assert_eq!(2, struct_2.0); 156 | assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); 157 | assert_eq!(0, struct_4.0); 158 | assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); 159 | assert_eq!("", struct_str.0); 160 | } 161 | } 162 | 163 | mod and_method_is_val_method { 164 | use super::*; 165 | 166 | #[test] 167 | fn and_not_mocked_then_runs_normally() { 168 | assert_eq!("2 true 1.5", Struct(2u8).val_method(true, 1.5f32)); 169 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 170 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 171 | } 172 | 173 | #[test] 174 | fn and_continue_mocked_then_runs_with_modified_args() { 175 | unsafe { 176 | Struct::::val_method:: 177 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3u8), !b, c + 1.))); 178 | } 179 | 180 | assert_eq!("3 false 2.5", Struct(2u8).val_method(true, 1.5f32)); 181 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 182 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 183 | } 184 | 185 | #[test] 186 | fn and_return_mocked_then_returns_mocking_result() { 187 | unsafe { 188 | Struct::::val_method:: 189 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 190 | } 191 | 192 | assert_eq!("mocked 2 true 1.5", Struct(2u8).val_method(true, 1.5f32)); 193 | assert_eq!("2 true abc", Struct(2u8).val_method(true, "abc")); 194 | assert_eq!("abc true 1.5", Struct("abc").val_method(true, 1.5f32)); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_regular_struct_generic_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool) -> String; 5 | fn ref_method(&self, arg: bool) -> String; 6 | fn ref_mut_method(&mut self, arg: bool) -> String; 7 | fn val_method(self, arg: bool) -> String; 8 | } 9 | 10 | struct Struct(T); 11 | 12 | #[mockable] 13 | impl Trait for Struct { 14 | fn static_method(arg: bool) -> String { 15 | format!("{}", arg) 16 | } 17 | 18 | fn ref_method(&self, arg: bool) -> String { 19 | format!("{} {}", self.0, arg) 20 | } 21 | 22 | fn ref_mut_method(&mut self, arg: bool) -> String { 23 | self.0 = T::default(); 24 | format!("{} {}", self.0, arg) 25 | } 26 | 27 | fn val_method(self, arg: bool) -> String { 28 | format!("{} {}", self.0, arg) 29 | } 30 | } 31 | 32 | mod and_method_is_static { 33 | use super::*; 34 | 35 | #[test] 36 | fn and_not_mocked_then_runs_normally() { 37 | assert_eq!("true", Struct::::static_method(true)); 38 | assert_eq!("true", Struct::<&str>::static_method(true)); 39 | } 40 | 41 | #[test] 42 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 43 | unsafe { 44 | Struct::::static_method.mock_raw(|a| MockResult::Continue((!a,))); 45 | } 46 | 47 | assert_eq!("false", Struct::::static_method(true)); 48 | assert_eq!("true", Struct::<&str>::static_method(true)); 49 | } 50 | 51 | #[test] 52 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 53 | unsafe { 54 | Struct::::static_method.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 55 | } 56 | 57 | assert_eq!("mocked true", Struct::::static_method(true)); 58 | assert_eq!("true", Struct::<&str>::static_method(true)); 59 | } 60 | } 61 | 62 | mod and_method_is_ref_method { 63 | use super::*; 64 | 65 | #[test] 66 | fn and_not_mocked_then_runs_normally() { 67 | assert_eq!("2 true", Struct(2u8).ref_method(true)); 68 | assert_eq!("abc true", Struct("abc").ref_method(true)); 69 | } 70 | 71 | #[test] 72 | fn and_continue_mocked_then_runs_with_modified_args() { 73 | let struct_2 = Struct(2u8); 74 | let struct_3 = Struct(3u8); 75 | unsafe { 76 | Struct::::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 77 | } 78 | 79 | assert_eq!("3 false", struct_2.ref_method(true)); 80 | assert_eq!(2, struct_2.0); 81 | assert_eq!(3, struct_3.0); 82 | assert_eq!("abc true", Struct("abc").ref_method(true)); 83 | } 84 | 85 | #[test] 86 | fn and_return_mocked_then_returns_mocking_result() { 87 | let struct_2 = Struct(2u8); 88 | unsafe { 89 | Struct::::ref_method 90 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 91 | } 92 | 93 | assert_eq!("mocked 2 true", struct_2.ref_method(true)); 94 | assert_eq!(2, struct_2.0); 95 | assert_eq!("abc true", Struct("abc").ref_method(true)); 96 | } 97 | } 98 | 99 | mod and_method_is_ref_mut_method { 100 | use super::*; 101 | 102 | #[test] 103 | fn and_not_mocked_then_runs_normally() { 104 | let mut struct_2 = Struct(2u8); 105 | let mut struct_str = Struct("str"); 106 | 107 | assert_eq!("0 true", struct_2.ref_mut_method(true)); 108 | assert_eq!(0, struct_2.0); 109 | assert_eq!(" true", struct_str.ref_mut_method(true)); 110 | assert_eq!("", struct_str.0); 111 | } 112 | 113 | #[test] 114 | fn and_continue_mocked_then_runs_with_modified_args() { 115 | let mut struct_2 = Struct(2u8); 116 | let struct_3 = Struct(3u8); 117 | let mut struct_str = Struct("str"); 118 | unsafe { 119 | Struct::::ref_mut_method 120 | .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 121 | } 122 | 123 | assert_eq!("0 false", struct_2.ref_mut_method(true)); 124 | assert_eq!(2, struct_2.0); 125 | assert_eq!(0, struct_3.0); 126 | assert_eq!(" true", struct_str.ref_mut_method(true)); 127 | assert_eq!("", struct_str.0); 128 | } 129 | 130 | #[test] 131 | fn and_return_mocked_then_returns_mocking_result() { 132 | let mut struct_2 = Struct(2u8); 133 | let mut struct_str = Struct("str"); 134 | unsafe { 135 | Struct::::ref_mut_method 136 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 137 | } 138 | 139 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true)); 140 | assert_eq!(2, struct_2.0); 141 | assert_eq!(" true", struct_str.ref_mut_method(true)); 142 | assert_eq!("", struct_str.0); 143 | } 144 | } 145 | 146 | mod and_method_is_val_method { 147 | use super::*; 148 | 149 | #[test] 150 | fn and_not_mocked_then_runs_normally() { 151 | assert_eq!("2 true", Struct(2u8).val_method(true)); 152 | assert_eq!("abc true", Struct("abc").val_method(true)); 153 | } 154 | 155 | #[test] 156 | fn and_continue_mocked_then_runs_with_modified_args() { 157 | unsafe { 158 | Struct::::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3u8), !b))); 159 | } 160 | 161 | assert_eq!("3 false", Struct(2u8).val_method(true)); 162 | assert_eq!("abc true", Struct("abc").val_method(true)); 163 | } 164 | 165 | #[test] 166 | fn and_return_mocked_then_returns_mocking_result() { 167 | unsafe { 168 | Struct::::val_method 169 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 170 | } 171 | 172 | assert_eq!("mocked 2 true", Struct(2u8).val_method(true)); 173 | assert_eq!("abc true", Struct("abc").val_method(true)); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_regular_struct_regular_method_generic.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool, method_generic: T) -> String; 5 | fn ref_method(&self, arg: bool, method_generic: T) -> String; 6 | fn ref_mut_method(&mut self, arg: bool, method_generic: T) -> String; 7 | fn val_method(self, arg: bool, method_generic: T) -> String; 8 | } 9 | 10 | struct Struct(u8); 11 | 12 | #[mockable] 13 | impl Trait for Struct { 14 | fn static_method(arg: bool, method_generic: T) -> String { 15 | format!("{} {}", arg, method_generic) 16 | } 17 | 18 | fn ref_method(&self, arg: bool, method_generic: T) -> String { 19 | format!("{} {} {}", self.0, arg, method_generic) 20 | } 21 | 22 | fn ref_mut_method(&mut self, arg: bool, method_generic: T) -> String { 23 | self.0 *= 2; 24 | format!("{} {} {}", self.0, arg, method_generic) 25 | } 26 | 27 | fn val_method(self, arg: bool, method_generic: T) -> String { 28 | format!("{} {} {}", self.0, arg, method_generic) 29 | } 30 | } 31 | 32 | mod and_method_is_static { 33 | use super::*; 34 | 35 | #[test] 36 | fn and_not_mocked_then_runs_normally() { 37 | assert_eq!("true 1.5", Struct::static_method(true, 1.5f32)); 38 | assert_eq!("true abc", Struct::static_method(true, "abc")); 39 | } 40 | 41 | #[test] 42 | fn and_continue_mocked_then_runs_with_modified_args_for_mocked_type_only() { 43 | unsafe { 44 | Struct::static_method::.mock_raw(|a, b| MockResult::Continue((!a, b + 1.))); 45 | } 46 | 47 | assert_eq!("false 3.5", Struct::static_method(true, 2.5f32)); 48 | assert_eq!("true abc", Struct::static_method(true, "abc")); 49 | } 50 | 51 | #[test] 52 | fn and_return_mocked_then_returns_mocking_result_for_mocked_type_only() { 53 | unsafe { 54 | Struct::static_method:: 55 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a, b))); 56 | } 57 | 58 | assert_eq!("mocked true 2.5", Struct::static_method(true, 2.5f32)); 59 | assert_eq!("true abc", Struct::static_method(true, "abc")); 60 | } 61 | } 62 | 63 | mod and_method_is_ref_method { 64 | use super::*; 65 | 66 | #[test] 67 | fn and_not_mocked_then_runs_normally() { 68 | assert_eq!("2 true 1.5", Struct(2).ref_method(true, 1.5f32)); 69 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 70 | } 71 | 72 | #[test] 73 | fn and_continue_mocked_then_runs_with_modified_args() { 74 | let struct_2 = Struct(2); 75 | let struct_3 = Struct(3); 76 | unsafe { 77 | Struct::ref_method:: 78 | .mock_raw(|_, b, c| MockResult::Continue((&struct_3, !b, c + 1.))); 79 | } 80 | 81 | assert_eq!("3 false 2.5", struct_2.ref_method(true, 1.5f32)); 82 | assert_eq!(2, struct_2.0); 83 | assert_eq!(3, struct_3.0); 84 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 85 | } 86 | 87 | #[test] 88 | fn and_return_mocked_then_returns_mocking_result() { 89 | let struct_2 = Struct(2); 90 | unsafe { 91 | Struct::ref_method:: 92 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 93 | } 94 | 95 | assert_eq!("mocked 2 true 1.5", struct_2.ref_method(true, 1.5f32)); 96 | assert_eq!(2, struct_2.0); 97 | assert_eq!("2 true abc", Struct(2).ref_method(true, "abc")); 98 | } 99 | } 100 | 101 | mod and_method_is_ref_mut_method { 102 | use super::*; 103 | 104 | #[test] 105 | fn and_not_mocked_then_runs_normally() { 106 | let mut struct_2 = Struct(2); 107 | let mut struct_4 = Struct(4); 108 | 109 | assert_eq!("4 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 110 | assert_eq!(4, struct_2.0); 111 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 112 | assert_eq!(8, struct_4.0); 113 | } 114 | 115 | #[test] 116 | fn and_continue_mocked_then_runs_with_modified_args() { 117 | let mut struct_2 = Struct(2); 118 | let struct_3 = Struct(3); 119 | let mut struct_4 = Struct(4); 120 | unsafe { 121 | Struct::ref_mut_method:: 122 | .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); 123 | } 124 | 125 | assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); 126 | assert_eq!(2, struct_2.0); 127 | assert_eq!(6, struct_3.0); 128 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 129 | assert_eq!(8, struct_4.0); 130 | } 131 | 132 | #[test] 133 | fn and_return_mocked_then_returns_mocking_result() { 134 | let mut struct_2 = Struct(2); 135 | let mut struct_4 = Struct(4); 136 | unsafe { 137 | Struct::ref_mut_method:: 138 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 139 | } 140 | 141 | assert_eq!("mocked 2 true 1.5", struct_2.ref_mut_method(true, 1.5f32)); 142 | assert_eq!(2, struct_2.0); 143 | assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); 144 | assert_eq!(8, struct_4.0); 145 | } 146 | } 147 | 148 | mod and_method_is_val_method { 149 | use super::*; 150 | 151 | #[test] 152 | fn and_not_mocked_then_runs_normally() { 153 | assert_eq!("2 true 1.5", Struct(2).val_method(true, 1.5f32)); 154 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 155 | } 156 | 157 | #[test] 158 | fn and_continue_mocked_then_runs_with_modified_args() { 159 | unsafe { 160 | Struct::val_method:: 161 | .mock_raw(move |_, b, c| MockResult::Continue((Struct(3), !b, c + 1.))); 162 | } 163 | 164 | assert_eq!("3 false 2.5", Struct(2).val_method(true, 1.5f32)); 165 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 166 | } 167 | 168 | #[test] 169 | fn and_return_mocked_then_returns_mocking_result() { 170 | unsafe { 171 | Struct::val_method:: 172 | .mock_raw(|a, b, c| MockResult::Return(format!("mocked {} {} {}", a.0, b, c))); 173 | } 174 | 175 | assert_eq!("mocked 2 true 1.5", Struct(2).val_method(true, 1.5f32)); 176 | assert_eq!("2 true abc", Struct(2).val_method(true, "abc")); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /tests/mocking_traits/when_trait_regular_struct_regular_method_regular.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | trait Trait { 4 | fn static_method(arg: bool) -> String; 5 | fn ref_method(&self, arg: bool) -> String; 6 | fn ref_mut_method(&mut self, arg: bool) -> String; 7 | fn val_method(self, arg: bool) -> String; 8 | } 9 | 10 | struct Struct(u8); 11 | 12 | #[mockable] 13 | impl Trait for Struct { 14 | fn static_method(arg: bool) -> String { 15 | format!("{}", arg) 16 | } 17 | 18 | fn ref_method(&self, arg: bool) -> String { 19 | format!("{} {}", self.0, arg) 20 | } 21 | 22 | fn ref_mut_method(&mut self, arg: bool) -> String { 23 | self.0 *= 2; 24 | format!("{} {}", self.0, arg) 25 | } 26 | 27 | fn val_method(self, arg: bool) -> String { 28 | format!("{} {}", self.0, arg) 29 | } 30 | } 31 | 32 | mod and_method_is_static { 33 | use super::*; 34 | 35 | #[test] 36 | fn and_not_mocked_then_runs_normally() { 37 | assert_eq!("true", Struct::static_method(true)); 38 | } 39 | 40 | #[test] 41 | fn and_continue_mocked_then_runs_with_modified_args() { 42 | unsafe { 43 | Struct::static_method.mock_raw(|a| MockResult::Continue((!a,))); 44 | } 45 | 46 | assert_eq!("false", Struct::static_method(true)); 47 | } 48 | 49 | #[test] 50 | fn and_return_mocked_then_returns_mocking_result() { 51 | unsafe { 52 | Struct::static_method.mock_raw(|a| MockResult::Return(format!("mocked {}", a))); 53 | } 54 | 55 | assert_eq!("mocked true", Struct::static_method(true)); 56 | } 57 | } 58 | 59 | mod and_method_is_ref_method { 60 | use super::*; 61 | 62 | #[test] 63 | fn and_not_mocked_then_runs_normally() { 64 | assert_eq!("2 true", Struct(2).ref_method(true)); 65 | } 66 | 67 | #[test] 68 | fn and_continue_mocked_then_runs_with_modified_args() { 69 | let struct_2 = Struct(2); 70 | let struct_3 = Struct(3); 71 | unsafe { 72 | Struct::ref_method.mock_raw(|_, b| MockResult::Continue((&struct_3, !b))); 73 | } 74 | 75 | assert_eq!("3 false", struct_2.ref_method(true)); 76 | assert_eq!(2, struct_2.0); 77 | assert_eq!(3, struct_3.0); 78 | } 79 | 80 | #[test] 81 | fn and_return_mocked_then_returns_mocking_result() { 82 | let struct_2 = Struct(2); 83 | unsafe { 84 | Struct::ref_method.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 85 | } 86 | 87 | assert_eq!("mocked 2 true", struct_2.ref_method(true)); 88 | assert_eq!(2, struct_2.0); 89 | } 90 | } 91 | 92 | mod and_method_is_ref_mut_method { 93 | use super::*; 94 | 95 | #[test] 96 | fn and_not_mocked_then_runs_normally() { 97 | let mut struct_2 = Struct(2); 98 | 99 | assert_eq!("4 true", struct_2.ref_mut_method(true)); 100 | assert_eq!(4, struct_2.0); 101 | } 102 | 103 | #[test] 104 | fn and_continue_mocked_then_runs_with_modified_args() { 105 | let mut struct_2 = Struct(2); 106 | let struct_3 = Struct(3); 107 | unsafe { 108 | Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); 109 | } 110 | 111 | assert_eq!("6 false", struct_2.ref_mut_method(true)); 112 | assert_eq!(2, struct_2.0); 113 | assert_eq!(6, struct_3.0); 114 | } 115 | 116 | #[test] 117 | fn and_return_mocked_then_returns_mocking_result() { 118 | let mut struct_2 = Struct(2); 119 | unsafe { 120 | Struct::ref_mut_method 121 | .mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 122 | } 123 | 124 | assert_eq!("mocked 2 true", struct_2.ref_mut_method(true)); 125 | assert_eq!(2, struct_2.0); 126 | } 127 | } 128 | 129 | mod and_method_is_val_method { 130 | use super::*; 131 | 132 | #[test] 133 | fn and_not_mocked_then_runs_normally() { 134 | assert_eq!("2 true", Struct(2).val_method(true)); 135 | } 136 | 137 | #[test] 138 | fn and_continue_mocked_then_runs_with_modified_args() { 139 | unsafe { 140 | Struct::val_method.mock_raw(move |_, b| MockResult::Continue((Struct(3), !b))); 141 | } 142 | 143 | assert_eq!("3 false", Struct(2).val_method(true)); 144 | } 145 | 146 | #[test] 147 | fn and_return_mocked_then_returns_mocking_result() { 148 | unsafe { 149 | Struct::val_method.mock_raw(|a, b| MockResult::Return(format!("mocked {} {}", a.0, b))); 150 | } 151 | 152 | assert_eq!("mocked 2 true", Struct(2).val_method(true)); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /tests/module_annotated_declaration/mod.rs: -------------------------------------------------------------------------------- 1 | pub fn function() -> &'static str { 2 | "not mocked" 3 | } 4 | --------------------------------------------------------------------------------