7

I've modeled and implemented a car using an extern crate inside the implementation:

extern crate speed_control;

struct Car;

trait SpeedControl {
    fn increase(&self) -> Result<(), ()>;
    fn decrease(&self) -> Result<(), ()>;
}

impl SpeedControl for Car {
    fn increase(&self) -> Result<(), ()> {
        match speed_control::increase() {  // Here I use the dependency
          // ... 
        }
    }
    // ...
}

I want to test the implementation above, but in my tests I don't want speed_control::increase() to behave like it was in production - I want to mock it. How can I achieve this?

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
simeg
  • 1,889
  • 2
  • 26
  • 34

1 Answers1

13

I would suggest you wrap the back-end function speed_control::increase in some trait:

trait SpeedControlBackend {
    fn increase();
}

struct RealSpeedControl;

impl SpeedControlBackend for RealSpeedControl {
    fn increase() {
        speed_control::increase();
    }
}

struct MockSpeedControl;

impl SpeedControlBackend for MockSpeedControl {
    fn increase() {
        println!("MockSpeedControl::increase called");
    }
}

trait SpeedControl {
    fn other_function(&self) -> Result<(), ()>;
}

struct Car<T: SpeedControlBackend> {
    sc: T,
}

impl<T: SpeedControlBackend> SpeedControl for Car<T> {
    fn other_function(&self) -> Result<(), ()> {
        match self.sc.increase() {
            () => (),
        }
    }
}
simeg
  • 1,889
  • 2
  • 26
  • 34
mcarton
  • 27,633
  • 5
  • 85
  • 95