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
- Broadest term: Test Double. They are all part of this category
- Test Dummy: An object that stands in for another, that has no methods. Not very useful.
- Stub: Responds to the key methods that are required for the test but the return values are fixed.
- 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.
- Performance
- Maintainability
- Testability
- If you introduce a bug in a class
- Only the tests that are testing that class will fail
- So, fewer false positives
- Disadvantages
- Need to maintain to consistency between the mock and the class-being-mocked
- Otherwise you may be testing somethingn that doesn’t even exist
- Real world example:
- Let’s look at some of the code that runs this web site.
- Note slightly different syntax because of RSpec vs. minitest/spec
- citem_spec.rb
- toc_spec.rb