public
Last active

Playing around with ruby mocking, interfaces and communication.

  • Download Gist
ruby_interface.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
# In ruby you can mock everything, but get no indication when you forget to change underlying methods.
# In Java, this would be picked up by the compiler.
# This makes mocking in ruby more fragile.
# What if you were only allowed to mock methods on an "interface"? In the simple case
# this is just a class, but could be a module for re-use.
 
require 'minitest/unit'
require 'minitest/mock'
require 'minitest/autorun'
 
class UserDAO
def update_email(email)
# ...
end
end
 
class UserUpdater
def update_details(dao, attributes)
dao.update_name_and_email(attributes[:name], attributes[:email])
end
end
 
class InterfaceMock < MiniTest::Mock
def initialize(interface)
@interface = interface
super()
end
 
def expect(method_name, *args)
unless @interface.instance_methods(false).include?(method_name)
raise "Attempted to stub #{method_name} which doesn't exist on #{@interface}"
end
 
super
end
end
 
class UserUpdaterTest < MiniTest::Unit::TestCase
def test_update_details_updates_email
dao = InterfaceMock.new(UserDAO)
# dao = MiniTest::Mock.new
dao.expect(:update_name_and_email, nil, ['don', 'hello@example.com'])
updater = UserUpdater.new
updater.update_details(dao, name: 'don', email: 'hello@example.com')
dao.verify
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.