Mocking slides |

Overview

  • SUT (“System under test”)
  • Collaborators (other objects needed to test SUT)
  • Decoupling is a major goal

example


# code sketch, not valid code!

#
# This car class has many methods which would call an API to retrieve information,
# For example, whether a car is electric is retrieved from the make, model and year.
#
class Car
   def make
   def model
   def year
   def electric?
   def suv?
   def current_price
   def to_html # this method would be used to render the car on a web pagte
end

# The Garage and Space classes need to work with Car. But, all they 
# need is whether the car is electric or whether it is an suv. That is enough
# to choose the best space for the car.

class Garage
   # Allocates an array of floors, containing arrays of spaces
   def initialize(floors, spaces_per_floor)

   # Given the 
   def find_parking_space(car)
   def park_car(car, space)
   def contains_space(space)
end

class Space
    def is_free?
    def occupied?
    def fits_suv?
    def charging_station?
    def occupying_car # returns the car occupying the space
end

# sketch of test
    c = Car.new(year: 2021, model: "Sierra", make: "Toyota")
    g = Garage.new(floors: 3,   spaces_per_floor: 10)
    space = g.find_parking_space(c)
    assert_nill space
    g.park_car(c, space)
    assert space.occupied?

    1..10.times do
      car = Car.new(...) # How do we deal with the database calls and the API calls?
      space = g.find_parking_space(car)
      g.park_car(car, space)
    end

What is a Mock?

  • An object that stands in for another object during testing
  • Make sure that only the right methods are called
  • Related terms: Test Doubles, stubs, and others. Don’t get confused.
  • More distinctions
    1. Broadest term: Test Double. They are all part of this category
    2. Test Dummy: An object that stands in for another, that has no methods. Not very useful.
    3. Stub: Responds to the key methods that are required for the test but the return values are fixed.
    4. Spy: Like a Stub, except it “remembers” what calls were made so it can verify that the expected calls were indeed made.


    car1 = Minitest::Mock.new
    mock.expect :electric, false

Advantages and Disadvantages

  • Decoupling is always a good thing.
    1. Performance
    2. Maintainability
    3. Testability
  • If you introduce a bug in a class
    1. Only the tests that are testing that class will fail
    2. So, fewer false positives
  • Disadvantages
    1. Need to maintain to consistency between the mock and the class-being-mocked
    2. Otherwise you may be testing somethingn that doesn’t even exist
  • Real world example:
    1. Let’s look at some of the code that runs this web site.
    2. Note slightly different syntax because of RSpec vs. minitest/spec
    3. citem_spec.rb
    4. toc_spec.rb