A test double is a generic (meta) term used for these objects or procedures.
A test double is a generic (meta) term buzzword used for these objects or procedures.
In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways.
require 'time'
class Ticket < Struct.new(:time)
def expired?
Time.parse(time) < Time.now
end
end
Ticket.new('2015-09-11').expired?
require 'socket'
sock = TCPSocket.new('t.co', 80)
sock.write("GET / HTTP/1.0\r\nHost: t.co\r\n\r\n")
begin
IO.select([sock])
sock.read_nonblock(256)
rescue IO::WaitReadable
retry # How to test this clause?
end
sock.close
data = File.read('/dev/random', 2**20)
require 'socket'
sock = TCPSocket.new('t.co', 80)
sock.write("POST / HTTP/1.0\r\nHost: t.co\r\n\r\n")
sock.write(data)
sock.close
Because RR has/had some bugs and it is too complex for me to fix it.
require 'pork/auto'
require 'muack'
describe Kernel do
include Muack::API
before{ Muack.reset }
after { Muack.verify }
would 'puts' do
mock(self).puts(is_a(String)){ ok }
puts "Hello!"
end
end
class Ticket < Struct.new(:time)
def expired?
Time.parse(time) < Time.now
end
end
Ticket.new('2015-09-11').expired?
class Ticket < Struct.new(:time)
def expired?
Time.parse(time) < Time.now
end
end
describe Ticket do
would 'not expired?' do
mock(Time).now{ Time.at(0) }
Ticket.new('2015-09-11').expired?
end
end
class Ticket < Struct.new(:time)
def expired?
Time.parse(time) < Time.now
end
end
describe Ticket do
would 'not expired?' do
mock(Time).now{ Time.at(0) }
expect(Ticket.new('2015-09-11')).not.expired?
end
end
describe Ticket do
would 'expired?' do
mock(Time).now{ Time.parse('2015-09-12') }
expect(Ticket.new('2015-09-11')).expired?
end
would 'not expired?' do
mock(Time).now{ Time.at(0) }
expect(Ticket.new('2015-09-11')).not.expired?
end
end
class Ticket < Struct.new(:time, :time_class)
def initialize new_time, new_time_class=Time
super(new_time, new_time_class)
end
def expired?
Time.parse(time) < time_class.now
end
end
describe Ticket do
would 'expired?' do
t = Struct.new(:now).new(Time.parse('2015-09-12'))
expect(Ticket.new('2015-09-11', t)).expired?
end
would 'not expired?' do
t = Struct.new(:now).new(Time.at(0))
expect(Ticket.new('2015-09-11', t)).not.expired?
end
end
Classification between mocks, fakes, and stubs is highly inconsistent across literature.
[...]
Which of the mock, fake, or stub is the simplest is inconsistent, but the simplest always returns pre-arranged responses.
A test double is a generic (meta) term buzzword used for these objects or procedures.
In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways.
describe Ticket do
would 'expired?' do
t = Struct.new(:now).new(Time.parse('2015-09-12'))
expect(Ticket.new('2015-09-11', t)).expired?
end
would 'not expired?' do
t = Struct.new(:now).new(Time.at(0))
expect(Ticket.new('2015-09-11', t)).not.expired?
end
end
describe Ticket do
would 'expired?' do
t = stub.now{ Time.parse('2015-09-12') }.object
expect(Ticket.new('2015-09-11', t)).expired?
end
would 'not expired?' do
t = stub.now{ Time.at(0) }.object
expect(Ticket.new('2015-09-11', t)).not.expired?
end
end
describe Ticket do
would 'expired?' do
t = mock.now{ Time.parse('2015-09-12') }.object
expect(Ticket.new('2015-09-11', t)).expired?
end
would 'not expired?' do
t = mock.now{ Time.at(0) }.object
expect(Ticket.new('2015-09-11', t)).not.expired?
end
end
describe Ticket do
would 'expired?' do
t = stub.now{ Time.parse('2015-09-12') }.object
expect(Ticket.new('2015-09-11', t)).expired?
spy(t).now
end
end
describe Ticket do
would 'expired?' do
stub(Time).now{ Time.parse('2015-09-12') }
expect(Ticket.new('2015-09-11')).expired?
spy(Time).now
Muack.verify
Time.now # => real time here
end
end
describe Ticket do
would 'expired?' do
coat(Time).now{ Time.parse('2015-09-12') }
expect(Ticket.new('2015-09-11')).expired?
Time.now # => real time here
end
end
There are chances that we don't really want to change the underlying implementation for a given method, but we still want to make sure the named method is called, and that's what we're testing for.
Partial mode is not really a mode, but a combination of using proxy mode and the pattern matching mechanism specialized in stubs.
any_instance_of
Well, sort of a hack to avoid dependency injection yet making it testable.
any_instance_of
shares all calls for a given class
WebMock.disable_net_connect!
copy :automock do
before do
stub(Notify).new_notification.
with_any_args.peek_args do |*args|
stub_firebase("notify/#{args.first.fid}")
args
end
end
end
describe Notify do
paste :automock
end
Model = Class.new(Sequel::Model)
copy :model do
def inserted; @inserted ||= {}; end
before do
test = self
stub(any_instance_of(Model))._insert.
peek_return(:instance_exec => true) do |r|
test.inserted[self.class.table_name] = true
r
end
end
after do
Model.truncate_all_tables!(inserted.keys)
end
end
Food = Class.new
User = Class.new(Struct.new(:food))
Muack::API.module_eval do
any_instance_of(User) do |user|
stub(user).food = is_a(Food) # proxy mode
end
end
u, f = User.new, Food.new
u.food = f # ok
u.food = 1 # raise Muack::Unexpected
Muack::API.stub(RailsAdmin::Config::Actions).find.
with_any_args.peek_args do |*args|
custom_key, bindings = args
if bindings && bindings[:object] &&
bindings[:object].id.nil?
# There's no show page for unsaved records
[nil, {}]
else
args # Bypass arguments
end
end