Skip to content

Commit

Permalink
Better panic messages for failed call counts
Browse files Browse the repository at this point in the history
The panic messages for a failed call counts panic will now include the
name of the method.

Fixes #31
  • Loading branch information
asomers committed Aug 19, 2019
1 parent f298efe commit 5961811
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 32 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased] - ReleaseDate
### Added
### Changed

- Better panic messages when an expectation fails its expected call count.
([#33](https://github.com/asomers/mockall/pull/33))

### Fixed

- Methods returning non-`'static` references (mutable or otherwise) will now
Expand Down
28 changes: 16 additions & 12 deletions mockall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,7 @@ impl From<RangeToInclusive<usize>> for TimesRange {
pub struct Times{
/// How many times has the expectation already been called?
count: AtomicUsize,
name: String,
range: TimesRange
}

Expand All @@ -1280,10 +1281,12 @@ impl Times {
let count = self.count.fetch_add(1, Ordering::Relaxed) + 1;
if count >= self.range.0.end {
if self.range.0.end == 1 {
panic!("Expectation should not have been called");
panic!("{}: Expectation should not have been called",
self.name);
} else {
let lim = self.range.0.end - 1;
panic!("Expectation called more than {} times", lim);
panic!("{}: Expectation called more than {} times", self.name,
lim);
}
}
}
Expand Down Expand Up @@ -1320,6 +1323,15 @@ impl Times {
self.range.0 = 0..1;
}

pub fn new<S: Into<String>>(name: S) -> Times {
// By default, allow any number of calls
Times {
count: AtomicUsize::default(),
name: name.into(),
range: TimesRange::default(),
}
}

pub fn range(&mut self, range: Range<usize>) {
assert!(range.end > range.start, "Backwards range");
self.range.0 = range;
Expand All @@ -1330,20 +1342,12 @@ impl Times {
}
}

impl Default for Times {
fn default() -> Self {
// By default, allow any number of calls
let count = AtomicUsize::default();
let range = TimesRange::default();
Times{count, range}
}
}

impl Drop for Times {
fn drop(&mut self) {
let count = self.count.load(Ordering::Relaxed);
if !thread::panicking() && (count < self.range.0.start) {
panic!("Expectation called fewer than {} times",
panic!("{}: Expectation called fewer than {} times",
self.name,
self.range.0.start);
}
}
Expand Down
12 changes: 8 additions & 4 deletions mockall/tests/mock_reference_arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
#[should_panic(expected =
"MockFoo::foo: Expectation called fewer than 2 times")]
fn too_few() {
let mut mock = MockFoo::new();
mock.expect_foo()
Expand All @@ -71,7 +72,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called more than 2 times")]
#[should_panic(expected =
"MockFoo::foo: Expectation called more than 2 times")]
fn too_many() {
let mut mock = MockFoo::new();
mock.expect_foo()
Expand All @@ -95,7 +97,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
#[should_panic(expected =
"MockFoo::foo: Expectation called fewer than 2 times")]
fn range_too_few() {
let mut mock = MockFoo::new();
mock.expect_foo()
Expand All @@ -105,7 +108,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called more than 3 times")]
#[should_panic(expected =
"MockFoo::foo: Expectation called more than 3 times")]
fn range_too_many() {
let mut mock = MockFoo::new();
mock.expect_foo()
Expand Down
3 changes: 2 additions & 1 deletion mockall/tests/mock_return_reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ mod never {
use super::*;

#[test]
#[should_panic(expected = "Expectation should not have been called")]
#[should_panic(expected =
"MockFoo::bar: Expectation should not have been called")]
fn fail() {
let mut mock = MockFoo::new();
mock.expect_bar()
Expand Down
24 changes: 16 additions & 8 deletions mockall/tests/mock_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ mod checkpoint {
}

#[test]
#[should_panic(expected = "Expectation called fewer than 1 times")]
#[should_panic(expected =
"MockFoo::foo: Expectation called fewer than 1 times")]
fn not_yet_satisfied() {
let mut mock = MockFoo::new();
mock.expect_foo()
Expand Down Expand Up @@ -159,7 +160,8 @@ mod never {
use super::*;

#[test]
#[should_panic(expected = "Expectation should not have been called")]
#[should_panic(expected =
"MockFoo::bar: Expectation should not have been called")]
fn fail() {
let mut mock = MockFoo::new();
mock.expect_bar()
Expand Down Expand Up @@ -294,7 +296,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
#[should_panic(expected =
"MockFoo::baz: Expectation called fewer than 2 times")]
fn too_few() {
let mut mock = MockFoo::new();
mock.expect_baz()
Expand All @@ -304,7 +307,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called more than 2 times")]
#[should_panic(expected =
"MockFoo::baz: Expectation called more than 2 times")]
fn too_many() {
let mut mock = MockFoo::new();
mock.expect_baz()
Expand Down Expand Up @@ -335,7 +339,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
#[should_panic(expected =
"MockFoo::baz: Expectation called fewer than 2 times")]
fn range_too_few() {
let mut mock = MockFoo::new();
mock.expect_baz()
Expand All @@ -345,7 +350,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called more than 3 times")]
#[should_panic(expected =
"MockFoo::baz: Expectation called more than 3 times")]
fn range_too_many() {
let mut mock = MockFoo::new();
mock.expect_baz()
Expand All @@ -371,7 +377,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called more than 3 times")]
#[should_panic(expected =
"MockFoo::baz: Expectation called more than 3 times")]
fn rangeto_too_many() {
let mut mock = MockFoo::new();
mock.expect_baz()
Expand Down Expand Up @@ -413,7 +420,8 @@ mod times {
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
#[should_panic(expected =
"MockFoo::baz: Expectation called fewer than 2 times")]
fn rangefrom_too_few() {
let mut mock = MockFoo::new();
mock.expect_baz()
Expand Down
3 changes: 2 additions & 1 deletion mockall/tests/mock_struct_with_static_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ mock!{
}

#[test]
#[should_panic(expected = "Expectation called fewer than 1 times")]
#[should_panic(expected =
"MockFoo::bar: Expectation called fewer than 1 times")]
fn checkpoint() {
let mut mock = MockFoo::new();
MockFoo::expect_bar()
Expand Down
3 changes: 2 additions & 1 deletion mockall_derive/src/automock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,8 @@ fn mock_function(vis: &Visibility,
Span::call_site());
let mut out = TokenStream::new();
Expectation::new(&TokenStream::new(), &inputs, None, generics,
&mod_ident, None, &decl.output, &expect_vis).to_tokens(&mut out);
&ident, &mod_ident, None, &decl.output, &expect_vis)
.to_tokens(&mut out);
quote!(
::mockall::lazy_static! {
static ref #obj: ::std::sync::Mutex<#expect_obj> =
Expand Down
21 changes: 17 additions & 4 deletions mockall_derive/src/expectation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ struct Common<'a> {
/// Types used for Predicates. Will be almost the same as args, but every
/// type will be a non-reference type.
predty: Vec<Type>,
/// name of the expectation's private module
/// name of the original method
meth_ident: &'a Ident,
/// name of the expectation's private module
mod_ident: &'a Ident,
/// Output type of the Method, supersuperfied.
output: Type,
/// Identifier of the parent structure, if any
parent_ident: Option<&'a Ident>,
/// Visibility of the expectation
/// TODO: supersuperfy it here rather than in the caller
vis: Visibility
Expand Down Expand Up @@ -280,7 +284,12 @@ impl<'a> Expectation<'a> {
pub(crate) fn gen(&self) -> TokenStream {
let argnames = &self.common().argnames;
let attrs = &self.common().attrs;
let ident = &self.common().meth_ident;
let ident = &self.common().mod_ident;
let ident_str = if let Some(pi) = self.common().parent_ident {
format!("{}::{}", pi, self.common().meth_ident)
} else {
format!("{}", self.common().meth_ident)
};
let extra_uses = self.extra_uses();
let fn_params = &self.common().fn_params;
let predty = &self.common().predty;
Expand Down Expand Up @@ -385,7 +394,7 @@ impl<'a> Expectation<'a> {
Common {
matcher: Mutex::new(Matcher::default()),
seq_handle: None,
times: ::mockall::Times::default()
times: ::mockall::Times::new(#ident_str)
}
}
}
Expand Down Expand Up @@ -496,6 +505,7 @@ impl<'a> Expectation<'a> {
/// slightly different than on the original method.
/// * `struct_generics` - Generics of the parent struct, if any.
/// * `meth_generics` - Generics of the method being mocked
/// * `mod_ident` - Name of the expectaton's private module
/// * `meth_ident` - Name of the original method
/// * `parent_ident` - Name of the parent struct, if any.
/// * `return_type` - Return type of the mock method
Expand All @@ -506,7 +516,8 @@ impl<'a> Expectation<'a> {
struct_generics: Option<&'a Generics>,
meth_generics: &'a Generics,
meth_ident: &'a Ident,
parent_ident: Option<&Ident>,
mod_ident: &'a Ident,
parent_ident: Option<&'a Ident>,
return_type: &ReturnType,
vis: &Visibility) -> Self
{
Expand Down Expand Up @@ -592,7 +603,9 @@ impl<'a> Expectation<'a> {
predexprs,
predty,
meth_ident,
mod_ident,
output,
parent_ident,
vis: vis.clone()
};
if ref_mut_expectation {
Expand Down
2 changes: 1 addition & 1 deletion mockall_derive/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ fn gen_struct<T>(mock_ident: &syn::Ident,

Expectation::new(&attrs, &meth_types.expectation_inputs,
Some(&generics), &meth_types.expectation_generics,
meth_ident, Some(&mock_ident), output,
meth_ident, meth_ident, Some(&mock_ident), output,
&expect_vis).to_tokens(&mut mod_body);

if meth_types.is_static {
Expand Down

0 comments on commit 5961811

Please sign in to comment.