Mockall - How to mock a function calling another function - rust

Suppose I have this trait which I am mocking using the Rust's mockall crate:
#[cfg(test)]
use mockall::automock;
#[cfg_attr(test, automock)]
trait MyTrait {
fn foo1(&self) -> u32 {
self.foo2(10)
}
fn foo2(&self, a: u32) -> u32 {
a + 1
}
}
#[cfg(test)]
mod tests {
use super::*;
use mockall::predicate;
#[test]
fn test() {
let mut m = MockMyTrait::new();
m.expect_foo2().with(predicate::eq(5u32));
m.expect_foo1().return_const(11u32);
assert_eq!(m.foo1(), 11);
}
}
My expectation here is that this is going to fail since the foo2 is called with the value 10 instead of the expected 5. However it succeeds. Is there a way to use this crate to test the internal workings of a function?

You can't both mock the trait and test the same trait.
What you're trying to accomplish here is some weird half-mock to test the default method implementations. This is not something that mockall supports. If you mock the trait, it will add hooks and checks to the whole trait; default implementations will not be considered.
You will have to test your trait manually:
trait MyTrait {
fn foo1(&self) -> u32 {
self.foo2(10)
}
fn foo2(&self, a: u32) -> u32 {
a + 1
}
}
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use super::*;
#[test]
fn my_trait_default_foo1_calls_foo2_with_10_and_returns_foo2_result() {
#[derive(Default)]
struct Test { foo2_was_called_with: RefCell<Option<u32>> }
impl MyTrait for Test {
fn foo2(&self, a: u32) -> u32 {
*self.foo2_was_called_with.borrow_mut() = Some(a);
42
}
}
let test = Test::default();
let result = test.foo1();
assert_eq!(result, 42);
assert_eq!(*test.foo2_was_called_with.borrow(), Some(10));
}
#[test]
fn my_trait_default_foo2_returns_incremented_argument() {
struct Test;
impl MyTrait for Test { }
let test = Test;
assert_eq!(test.foo2(0), 1);
assert_eq!(test.foo2(5), 6);
assert_eq!(test.foo2(42), 43);
}
}

You are using mock in wrong way. You do not depend on the behaviour of the actual implementation, instead, you create your own expectation and simulate the behaviour in each unit test.
In you example, you are missing the call to method and an associated return value.
You just create an expectation with argument matchers for this trait method signatures fn foo2(&self, a: u32) -> u32 by:
m.expect_foo2().with(predicate::eq(5u32))
However, you have to provide you own returning values for this expectiation
m.expect_foo2().with(predicate::eq(5u32)).returning(|x| x + 1)
Finnaly, you have to realize your expectation by calling the method:
assert_eq!(m.foo2(5), 6);
The code means you are expecting a call to foo2 with an input argument of 5u32 and will replace the foo2 implementation with |x| x + 1.

Related

How do I execute an implemented method in Rust?

I can't execute method which name is two_sum implemented in a Solution impl.
I want to know how to execute two_sum method from main.
My source code is here.
impl Solution {
pub fn two_sum(num: i32) -> i32 {
num + 1
}
}
fn main() {
let result = Solution::two_sum(1);
println!("{:?}", result);
}
Error message
failed to resolve: use of undeclared type Solution
use of undeclared type Solution
You need define what Solution is and later implement two_sum. One way is you can define Solution as an empty struct.
struct Solution;
impl Solution {
pub fn two_sum(num: i32) -> i32 {
num + 1
}
}
fn main() {
let result = Solution::two_sum(1);
println!("{:?}", result);
}
Well, firstly, your two_sum is an associated function, not a method. Secondly, it’s associated with nothing - you didn’t declare a type named Solution (you needed to write struct Solution; at least). Thirdly, you don’t need to Debug an i32, so we’ll replace {:?} with {}.
struct Solution;
impl Solution {
pub fn two_sum(num: i32) -> i32 {
num + 1
}
}
fn main() {
let result = Solution::two_sum(1);
println!("{}", result);
}
Fourthly, creating a type just to write a function is a really bad practice.
So what are we gonna do?
fn two_sum(num: i32) -> i32 {
num + 1
}
fn main() {
let result = two_sum(1);
println!("{}", result);
}
That’s it! I don’t know why did you call it two_sum tho.

Implement function for a struct returning a specific generic type

I am trying to return exclusively a f32 in my new function, inside an impl for Test struct. I am sure this isn't the best way to do it since I can call it with any type I want in the turbofish. Could you suggest me a better way of doing the same thing keeping the function as an impl of Test? Thanks.
use std::path::Path;
fn main() {
#[derive(Debug)]
struct Test<T> {
field: T
}
impl<T> Test<T> {
fn new() -> Test<f32> {
Test{field: 3_f32}
}
}
let b = Test::<i16>::new(); // i16 or i32 or whatever
println!("{:?}", b);
}
Your struct is generic, but your impl doesn't have to be.
impl Test<f32> {
fn new() -> Self {
Test { field: 3. }
}
}
Now, Test::new() will compile without any turbofish and the type is always Test<f32>.

Late type in Rust

I'm working with two crates: A and B. I control both. I'd like to create a struct in A that has a field whose type is known only to B (i.e., A is independent of B, but B is dependent on A).
crate_a:
#[derive(Clone)]
pub struct Thing {
pub foo: i32,
pub bar: *const i32,
}
impl Thing {
fn new(x: i32) -> Self {
Thing { foo: x, bar: &0 }
}
}
crate_b:
struct Value {};
fn func1() {
let mut x = A::Thing::new(1);
let y = Value {};
x.bar = &y as *const Value as *const i32;
...
}
fn func2() {
...
let y = unsafe { &*(x.bar as *const Value) };
...
}
This works, but it doesn't feel very "rusty". Is there a cleaner way to do this? I thought about using a trait object, but ran into issues with Clone.
Note: My reason for splitting these out is that the dependencies in B make compilation very slow. Value above is actually from llvm_sys. I'd rather not leak that into A, which has no other dependency on llvm.
The standard way to implement something like this is with generics, which are kind of like type variables: they can be "assigned" a particular type, possibly within some constraints. This is how the standard library can provide types like Vec that work with types that you declare in your crate.
Basically, generics allow Thing to be defined in terms of "some unknown type that will become known later when this type is actually used."
Given the example in your code, it looks like Thing's bar field may or may not be set, which suggests that the built-in Option enum should be used. All you have to do is put a type parameter on Thing and pass that through to Option, like so:
pub mod A {
#[derive(Clone)]
pub struct Thing<T> {
pub foo: i32,
pub bar: Option<T>,
}
impl<T> Thing<T> {
pub fn new(x: i32) -> Self {
Thing { foo: x, bar: None }
}
}
}
pub mod B {
use crate::A;
struct Value;
fn func1() {
let mut x = A::Thing::new(1);
let y = Value;
x.bar = Some(y);
// ...
}
fn func2(x: &A::Thing<Value>) {
// ...
let y: &Value = x.bar.as_ref().unwrap();
// ...
}
}
(Playground)
Here, the x in B::func1() has the type Thing<Value>. You can see with this syntax how Value is substituted for T, which makes the bar field Option<Value>.
If Thing's bar isn't actually supposed to be optional, just write pub bar: T instead, and accept a T in Thing::new() to initialize it:
pub mod A {
#[derive(Clone)]
pub struct Thing<T> {
pub foo: i32,
pub bar: T,
}
impl<T> Thing<T> {
pub fn new(x: i32, y: T) -> Self {
Thing { foo: x, bar: y }
}
}
}
pub mod B {
use crate::A;
struct Value;
fn func1() {
let mut x = A::Thing::new(1, Value);
// ...
}
fn func2(x: &A::Thing<Value>) {
// ...
let y: &Value = &x.bar;
// ...
}
}
(Playground)
Note that the definition of Thing in both of these cases doesn't actually require that T implement Clone; however, Thing<T> will only implement Clone if T also does. #[derive(Clone)] will generate an implementation like:
impl<T> Clone for Thing<T> where T: Clone { /* ... */ }
This can allow your type to be more flexible -- it can now be used in contexts that don't require T to implement Clone, while also being cloneable when T does implement Clone. You get the best of both worlds this way.

Can a Rust enum use methods implemented on one of its variants?

I think I misunderstand the purpose of enums.
I am looking to implement the XML DOM for practice. DOM nodes all have a list of methods associated with them, but some nodes (such as the document node) have additional methods not available on other nodes.
I was hoping to have all the main methods set up on the enum and then the variants would have the methods specific to them, but it seems like the method variants are not callable on an enum, but continue to be callable on the parameter.
#[derive(Clone, Debug, Copy)]
enum MyEnum {
MyType(MyType),
}
impl MyEnum {
pub fn do_a_thing(&self) -> i32 {
// Some code here
return 1;
}
}
#[derive(Clone, Debug, Copy)]
pub struct MyType {}
impl MyType {
pub fn do_another_thing(self) -> i32 {
// Some more code here
return 2;
}
}
fn main() {
let x = MyEnum::MyType(MyType {});
println!("{:?}", x);
println!("I can call do_a_thing, it is {}", x.do_a_thing());
println!(
"Why can't I call do_another_thing? {}",
x.do_another_thing()
);
}
This works fine, but my gut tells me I am going the wrong way about things:
impl MyEnum {
pub fn do_a_thing(&self) -> i32 {
// Some code here
return 1;
}
pub fn do_another_thing(self) -> i32 {
match self {
MyEnum::MyType(MT) => MT.do_another_thing(),
}
}
}
How should I implement this?
You are using an enum, so it's likely you're going to add more variants at some point (otherwise, why would you use enums, right?).
When Rust sees a value whose type is an enum, at compile-time it assumes the value could be any of the enum's variants, so it won't let you call a method on any variant until you check its type.
To do that is easy, as you've already shown in your question:
match self {
MyEnum::MyType(t) => t.do_another_thing()
}
You might be interested to know there's also if let in case you only want to check a single variant:
let x = MyEnum::MyType(MyType{});
if let MyEnum::MyType(t) = x {
t.do_another_thing();
}
You might want to have methods that are callable on ALL variants as well, in which case you'll need to either implement the method directly on the enum as you've done above, or use a trait that is implemented by the enum, which perhaps makes your code look more polymorphic as in most other languages (where there would be an interface for the nodes).
That will make your code in main work.
It might look like this:
#[derive(Clone, Debug, Copy)]
enum MyEnum {
MyType(MyType)
}
impl MyEnum {
pub fn do_a_thing(&self) -> i32{
// Some code here
return 1
}
}
#[derive(Clone, Debug, Copy)]
pub struct MyType {
}
trait MyTrait {
fn do_another_thing(&self) -> i32;
}
impl MyTrait for MyEnum {
fn do_another_thing(&self) -> i32 {
// Some more code here
return 2
}
}
fn main() {
let x = MyEnum::MyType(MyType{});
println!("{:?}",x);
println!("I can call do_a_thing, it is {}", x.do_a_thing());
println!("Why can't I call do_another_thing? {}", x.do_another_thing());
}

How to use traits for function overloading in Rust? [duplicate]

I am modeling an API where method overloading would be a good fit. My naïve attempt failed:
// fn attempt_1(_x: i32) {}
// fn attempt_1(_x: f32) {}
// Error: duplicate definition of value `attempt_1`
I then added an enum and worked through to:
enum IntOrFloat {
Int(i32),
Float(f32),
}
fn attempt_2(_x: IntOrFloat) {}
fn main() {
let i: i32 = 1;
let f: f32 = 3.0;
// Can't pass the value directly
// attempt_2(i);
// attempt_2(f);
// Error: mismatched types: expected enum `IntOrFloat`
attempt_2(IntOrFloat::Int(i));
attempt_2(IntOrFloat::Float(f));
// Ugly that the caller has to explicitly wrap the parameter
}
Doing some quick searches, I've found some references that talk about overloading, and all of them seem to end in "we aren't going to allow this, but give traits a try". So I tried:
enum IntOrFloat {
Int(i32),
Float(f32),
}
trait IntOrFloatTrait {
fn to_int_or_float(&self) -> IntOrFloat;
}
impl IntOrFloatTrait for i32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Int(*self)
}
}
impl IntOrFloatTrait for f32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Float(*self)
}
}
fn attempt_3(_x: &dyn IntOrFloatTrait) {}
fn main() {
let i: i32 = 1;
let f: f32 = 3.0;
attempt_3(&i);
attempt_3(&f);
// Better, but the caller still has to explicitly take the reference
}
Is this the closest I can get to method overloading? Is there a cleaner way?
Yes, there is, and you almost got it already. Traits are the way to go, but you don't need trait objects, use generics:
#[derive(Debug)]
enum IntOrFloat {
Int(i32),
Float(f32),
}
trait IntOrFloatTrait {
fn to_int_or_float(&self) -> IntOrFloat;
}
impl IntOrFloatTrait for i32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Int(*self)
}
}
impl IntOrFloatTrait for f32 {
fn to_int_or_float(&self) -> IntOrFloat {
IntOrFloat::Float(*self)
}
}
fn attempt_4<T: IntOrFloatTrait>(x: T) {
let v = x.to_int_or_float();
println!("{:?}", v);
}
fn main() {
let i: i32 = 1;
let f: f32 = 3.0;
attempt_4(i);
attempt_4(f);
}
See it working here.
Here's another way that drops the enum. It's an iteration on Vladimir's answer.
trait Tr {
fn go(&self) -> ();
}
impl Tr for i32 {
fn go(&self) {
println!("i32")
}
}
impl Tr for f32 {
fn go(&self) {
println!("f32")
}
}
fn attempt_1<T: Tr>(t: T) {
t.go()
}
fn main() {
attempt_1(1 as i32);
attempt_1(1 as f32);
}
Function Overloading is Possible!!! (well, sorta...)
This Rust Playground example has more a more detailed example, and shows usage of a struct variant, which may be better for documentation on the parameters.
For more serious flexible overloading where you want to have sets of any number of parameters of any sort of type, you can take advantage of the From<T> trait for conversion of a tuple to enum variants, and have a generic function that converts tuples passed into it to the enum type.
So code like this is possible:
fn main() {
let f = Foo { };
f.do_something(3.14); // One f32.
f.do_something((1, 2)); // Two i32's...
f.do_something(("Yay!", 42, 3.14)); // A str, i32, and f64 !!
}
First, define the different sets of parameter combinations as an enum:
// The variants should consist of unambiguous sets of types.
enum FooParam {
Bar(i32, i32),
Baz(f32),
Qux(&'static str, i32, f64),
}
Now, the conversion code; a macro can be written to do the tedious From<T> implementations, but here's what it could produce:
impl From<(i32, i32)> for FooParam {
fn from(p: (i32, i32)) -> Self {
FooParam::Bar(p.0, p.1)
}
}
impl From<f32> for FooParam {
fn from(p: f32) -> Self {
FooParam::Baz(p)
}
}
impl From<(&'static str, i32, f64)> for FooParam {
fn from(p: (&'static str, i32, f64)) -> Self {
FooParam::Qux(p.0, p.1, p.2)
}
}
And then finally, implement the struct with generic method:
struct Foo {}
impl Foo {
fn do_something<T: Into<FooParam>>(&self, t: T) {
use FooParam::*;
let fp = t.into();
match fp {
Bar(a, b) => print!("Bar: {:?}, {:?}\n", a, b),
Baz(a) => print!("Baz: {:?}\n", a),
Qux(a, b, c) => {
print!("Qux: {:?}, {:?}, {:?}\n", a, b, c)
}
}
}
}
Note: The trait bound on T needs to be specified.
Also, the variants need to be composed of combinations of types that the compiler wouldn't find ambiguous - which is an expectation for overloaded methods in other languages as well (Java/C++).
This approach has possibilities... it would be awesome if there's a decorator available - or one were written that did the From<T> implementations automatically when applied to an enum. Something like this:
// THIS DOESN'T EXIST - so don't expect the following to work.
// This is just an example of a macro that could be written to
// help in using the above approach to function overloading.
#[derive(ParameterOverloads)]
enum FooParam {
Bar(i32, i32),
Baz(f32),
Qux(&'static str, i32, f64),
}
// If this were written, it could eliminate the tedious
// implementations of From<...>.
The Builder
Another approach that addresses the case where you have multiple optional parameters to an action or configuration is the builder pattern. The examples below deviate somewhat from the recommendations in the link. Typically, there's a separate builder class/struct which finalizes the configuration and returns the configured object when a final method is invoked.
One of the most relevant situations this can apply to is where you want a constructor that takes a variable number of optional arguments - since Rust doesn't have built-in overloading, we can't have multiple versions of ___::new(). But we can get a similar effect using a chain of methods that return self. Playground link.
fn main() {
// Create.
let mut bb = BattleBot::new("Berzerker".into());
// Configure.
bb.flame_thrower(true)
.locomotion(TractorTreads)
.power_source(Uranium);
println!("{:#?}", bb);
}
Each of the configuration methods has a signature similar to:
fn power_source(&mut self, ps: PowerSource) -> &mut Self {
self.power_source = ps;
self
}
These methods could also be written to consume self and return non-reference copies or clones of self.
This approach can also be applied to actions. For instance, we could have a Command object that can be tuned with chained methods, which then performs the command when .exec() is invoked.
Applying this same idea to an "overloaded" method that we want to take a variable number of parameters, we modify our expectations a bit and have the method take an object that can be configured with the builder pattern.
let mut params = DrawParams::new();
graphics.draw_obj(params.model_path("./planes/X15.m3d")
.skin("./skins/x15.sk")
.location(23.64, 77.43, 88.89)
.rotate_x(25.03)
.effect(MotionBlur));
Alternatively, we could decide on having a GraphicsObject struct that has several config tuning methods, then performs the drawing when .draw() is invoked.

Resources