Behavior based testing has been criticized by state based advocates because it can cause test failures when implementation changes are made. In it's worst form, behavior based testing can be fragile. However, behavior based tests that avoid high implementation specification can effectively verify behavior without sacrificing maintainability.
The following test verifies the interaction between a Hotel instance and the ReservationService without the need to specify any other implementation detail. A change to book_for method will only cause the test to fail if the interaction between the two objects is changed, in which case a failing test is appropriate.
  # implementation
end
  attr_accessor :booked
  
    reservation = ReservationService.reserve_for(customer, self)
    self.booked = true
    MaidService.notify(reservation) if reservation.tomorrow?
    VipService.notify(reservation) if reservation.for_vip?
    reservation.confirmation_number
  end
end
  
    room = HotelRoom.new
    ReservationService.expects(:reserve_for).with(:customer, room).returns(stub_everything)
    room.book_for(:customer)
  end
endBehavior based tests are easy to spot because they focus on mock verification to ensure a system behaves as expected.
Developers who generally rely on behavior based tests can be considered Mockists. Martin Fowler has a great article, Mocks Aren't Stubs, that expands greatly on the ideas that are briefly mentioned here.
It's more useful to make a distinction between state-based and interaction-based verification, because ideally it's all behavior
ReplyDelete