Skip to content

Commit

Permalink
Merge pull request #373 from asomers/deselfify_args
Browse files Browse the repository at this point in the history
Fix mocking methods that use `Self` in their arguments.
  • Loading branch information
asomers committed May 4, 2022
2 parents 94f62cd + 1db92b6 commit 9096113
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).


## [ Unreleased ] - ReleaseDate

### Fixed

- Fixed mocking methods that use `Self` in their arguments, but not as the
receiver. For example, `PartialEq::eq` has a signature like
`fn eq(&self, other: &Self) -> bool`
([#373](https://github.com/asomers/mockall/pull/373))

## [ 0.11.0 ] - 2021-12-11

### Added
Expand Down
39 changes: 39 additions & 0 deletions mockall/tests/automock_partial_eq.rs
@@ -0,0 +1,39 @@
// vim: tw=80
//! Mockall should deselfify `Self` types, even if they aren't named `self`.
use mockall::*;

mock! {
#[derive(Debug)]
pub Foo {
fn compare(&self, other: &Self) -> bool;
}
impl PartialEq for Foo {
fn eq(&self, other: &Self) -> bool;
}
}

#[test]
fn inherent_method() {
let mut x = MockFoo::default();
let mut y = MockFoo::default();
x.expect_compare()
.return_const(true);
y.expect_compare()
.return_const(false);

assert!(x.compare(&y));
assert!(!y.compare(&x));
}

#[test]
fn trait_method() {
let mut x = MockFoo::default();
let mut y = MockFoo::default();
x.expect_eq()
.return_const(true);
y.expect_eq()
.return_const(false);

assert_eq!(x, y);
assert!(y != x);
}
14 changes: 14 additions & 0 deletions mockall_derive/src/lib.rs
Expand Up @@ -438,6 +438,20 @@ fn deselfify(literal_type: &mut Type, actual: &Ident, generics: &Generics) {
}
}

/// Change any `Self` in a method's arguments' types with `actual`.
/// `generics` is the Generics field of the parent struct.
fn deselfify_args(
args: &mut Punctuated<FnArg, Token![,]>,
actual: &Ident,
generics: &Generics)
{
for arg in args.iter_mut() {
if let FnArg::Typed(pt) = arg {
deselfify(&mut *pt.ty, actual, generics)
}
}
}

fn find_ident_from_path(path: &Path) -> (Ident, PathArguments) {
if path.segments.len() != 1 {
compile_error(path.span(),
Expand Down
2 changes: 2 additions & 0 deletions mockall_derive/src/mockable_struct.rs
Expand Up @@ -139,6 +139,7 @@ fn mockable_item_impl(mut impl_: ItemImpl, name: &Ident, generics: &Generics)
fn mockable_method(meth: &mut ImplItemMethod, name: &Ident, generics: &Generics)
{
demutify(&mut meth.sig.inputs);
deselfify_args(&mut meth.sig.inputs, name, generics);
add_lifetime_parameters(&mut meth.sig);
deimplify(&mut meth.sig.output);
if let ReturnType::Type(_, ty) = &mut meth.sig.output {
Expand All @@ -155,6 +156,7 @@ fn mockable_trait_method(
generics: &Generics)
{
demutify(&mut meth.sig.inputs);
deselfify_args(&mut meth.sig.inputs, name, generics);
add_lifetime_parameters(&mut meth.sig);
deimplify(&mut meth.sig.output);
if let ReturnType::Type(_, ty) = &mut meth.sig.output {
Expand Down

0 comments on commit 9096113

Please sign in to comment.