Rust how to check whether a function being called or not


#1

I’m looking for a way to check if a function is called once, many times or not by rust. Is this possible?


#2

Depends:

  • Is it your code? If so then just add a panic!() or a println!
  • Otherwise a wrapper of sorts would have to come into play; add a println! or panic before every call of the function or set a break point in a debugger.

#3

This is for unit tests. Im looking for a way to check another function being called from the function which the unit test has. @OptimisticPeach


#4

Hmm, then you’ve stumped me there, sorry I couldn’t help any more :disappointed:


#5

@OptimisticPeach No worries. Im trying to get my head around unit tests in Rust.


#6

You can’t. Also if a function calls another function is an implementation detail and should not be tested at all.

You are creating a coupling that makes future enhancement hard.


#7

You could write a proc macro, but I’m afraid (no offense!) this is a little bit too difficult for you (based on the thing that you are new to rust and try to get your head around how to do C#-ish things in Rust).
Just stick with println!.


#8

I’m interested about how you would do it. Even though I have not yet done procedural macros in rust, I’ve used macro rules and also have written macros in elixir and various lisp dialects.

I can not see how a macro could solve the problem, how would you implement assert_calls!(function_under_test, function_that_we_want_to_know_if_it_gets_called)? and its assert_calls_not!() counterpart such that the following suite works as expected?

fn bar() {}

fn foo(a: isize) {
  if a <= 0 {
    bar()
  }
}

#[test]
fn calls_it() {
  assert_calls!(foo(-1), bar())
}

#[test]
fn doesnt_call_it {
  assert_calls_not!(foo(1), bar())
}

#9
#[notify_when_called]
fn foo() -> &'static str {
    "FooBaaar"
}

#[notify_when_called]
fn comp() {
    assert_eq!("FooBar", foo());
}

Something like that?


#10

I do not understand.

What the OP wants is to know if foo() calls bar() under certain conditions. Your example looks like a regular unit test checking the result of a single function call, with some undocumented annotation.

Also as I see it, it would require me to annotate the actual function under test, and is not local to the testing function.


#11

I can’t read that from:

I’m looking for a way to check if a function is called once, many times or not by rust. Is this possible?

Meh, kind of. I don’t check anything. A proc macro can do anthing you want. I would do something like print a message to stderr so you can track the calling hirachie.

Of course it needs some manual intervention, because rust does not offer this functionality out of the box.


#12

Me neither, but from:

Maybe. To be honest, I’d actually be fine with annotating the function under test, but as I’m already working against rust, I think rethinking the testing strategy would actually be the better approach.

Usually I’d advice the usage of “service objects” here that implement a common interface and simply pass in a mock during unit tests, while passing in a proper implementation during production builds. But as I’m not sure about what or why the OP would want to test such a calling dependency I’m not sure if that suggestion is really appropriate.


#13

That’s a bad sign. :confused: Let us know if we can help you with anything!

Maybe instead of reinventing the wheel use a tool for that, e.g. https://medium.com/@Razican/continuous-integration-and-code-coverage-report-for-a-rust-project-5dfd4d68fbe5#3fa4 ?


#14

You misunderstood me. With testing such a thing, I’d working against rust.

Personally I’m not fighting rust, only the borrow checker, but often enough I’m the winner of those wrestles :wink: At least if I have time to do some rust at all.


#15

From your replies, it sounds like you’re asking for a spy, a particular kind of mock object, which is itself a kind of test double. Searching with those terms would likely find the best way to do that right now or if there are any crates, I’m not sure off the top of my head but I did find this presentation which might help.


#16

@NobbZ I Disagree
In unit tests we are testing whether a function is being called and it’s a common practice to mock and test it and the feature is commonly available in other languages


#17

A bit of googling brought me to this: https://asomers.github.io/mock_shootout/

Perhaps there is something burried for you?

As I said already, if I need to test something like this, I usually use mock “objects”.