Skip to content

Instantly share code, notes, and snippets.

@joegaudet
Last active December 11, 2018 20:23
Show Gist options
  • Save joegaudet/fc6313fac04a1a056107d940c1cb06f1 to your computer and use it in GitHub Desktop.
Save joegaudet/fc6313fac04a1a056107d940c1cb06f1 to your computer and use it in GitHub Desktop.
Update to the dependency system to support two types of null substitutes, one where the only public interface is call, and one where it is any method. This allows us to more simply test object boundaries.
module Broadcasters
class OrderBroadcaster
include Wisper::Publisher
include DependencySupport::NullSubstitute
def changed(order)
// do some stuff
end
end
end
# Basic Inert Class maps args to return values
class InertCallable
attr_reader :call_history
def initialize
@return = {}
@call_history = []
end
def call(*args)
@call_history << args
@return[args]
end
def setup(*args, ret)
@return[args] = ret
end
def called_with?(*args)
@call_history.include? args
end
def called_only_with?(*args)
@call_history == [args]
end
end
class InertNullObject
def initialize(parent_klass)
@methods = {}
@parent_klass = parent_klass
end
def method_missing(m, *args, &block)
raise NoMethodError, "The parent class #{@parent_klass} does not define a #{m} method" unless @parent_klass.method_defined?(m)
@methods[m] ||= InertCallable.new
args.length > 0 ? @methods[m].(*args) : @methods[m]
end
end
module NullSubstitute
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def inert
InertNullObject.new(self)
end
end
end
module Logistics
module ArrivalEstimates
class UpdateOrder < FoodeeService
dependency :find_estimate, Queries::ArrivalEstimates::FindOrCreateByOrder
dependency :save_record, Commands::SaveRecord
dependency :order_broadcaster, Broadcasters::OrderBroadcaster
def call(order, log)
estimate = find_estimate.(order.id)
estimate.update_estimate(log)
save_record.(order)
order_broadcaster.changed(order)
end
end
end
end
require 'test_helper'
module Logistics
module ArrivalEstimates
class UpdateOrderTest < ActiveSupport::TestCase
let(:update_order) {Logistics::ArrivalEstimates::UpdateOrder.as_subject}
let(:log) {Logistics::ArrivalEstimate::EstimateLog.new(timestamp: Time.current, arrival_estimate: Time.current + 1.hours)}
let(:order) {Order.new(id: 1)}
let(:estimate) {Logistics::ArrivalEstimate.new(id: 1, order: order)}
describe 'updating an order delivery estimate' do
context 'when the order is ready to be picked up' do
it 'updates the pickup estimate' do
order.state = 'driver_confirmed'
# Setup
update_order.find_estimate.setup(order.id, estimate)
update_order.save_record.setup(estimate)
# exercise
update_order.(order, log)
# assert
assert estimate.pickup_estimate == log
assert update_order.save_record.called_with_only? order
assert update_order.order_broadcaster.changed.called_only_with? order
end
end
context 'when the order is ready to be delivered' do
it 'updates the estimate' do
order.state = 'picked_up'
# Setup
update_order.find_estimate.setup(order.id, estimate)
update_order.save_record.setup(estimate)
# exercise
update_order.(order, log)
# assert
assert estimate.delivery_estimate == log
assert update_order.save_record.called_with_only? order
assert update_order.order_broadcaster.changed.called_only_with? order
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment