NAME
Test::Spy - build mocked interfaces and examine call data easily
SYNOPSIS
use Test::More;
use Test::Spy;
# create a spy
my $spy = Test::Spy->new;
# add a method
$spy->add_method('mocked_method')
->should_return('return value');
# create an object, execute the test
my $object = $spy->object;
print $object->mocked_method('argument'); # 'return value'
# examine the results
my $method = $spy->method('mocked_method');
ok $method->was_called;
is_deeply $method->called_with, ['argument'];
# examine the results - with context
$spy->set_context('mocked_method');
ok $spy->was_called;
is_deeply $spy->called_with, ['argument'];
done_testing;
DESCRIPTION
Test::Spy is a simple package for creating OO interface mocks, which can be verified on a per-method basis after the calls have been made.
This module will not replace methods in packages for you. It requires you to inject the generated object into your code with dependency injection.
Beta quality: interface is not yet stable before version 1.000.
Properties
base
Base object or package to use. Objects produced by Test::Spy will mimic the interface of its base object.
If an object is passed, it will be used directly. Otherwise, $base->new
will be called.
Test::Spy will only work properly with objects that are blessed hash references with no extra behavior like inside-out objects.
optional on the constructor with name: base
writer: set_base
predicate: has_base
imitates
Accepts package name or array reference of package names.
Causes isa
, DOES
and does
methods return true value if they are used to check the resulting object with the same package name. Similar to "base", but only affects object identity and will not call any methods or construct an object from class names. Useful if you want to make sure it passes some type checks, but will not actually call any unforeseen methods present in the base class.
$spy->set_imitates('Some::Package');
$spy->object->isa('Some::Package'); # true
$spy->object->does('Some::Package'); # true
$spy->object->DOES('Some::Package'); # true
$spy->object->isa('Other::Package'); # false
optional on the constructor with name: imitates
writer: set_imitates
predicate: has_imitates
interface
Strictness of the object interface. Can be any of:
'strict'
(default) - methods which were not mocked don't exist (exception)'lax'
- non-mocked methods are autoloaded and returnundef
'warn'
- same as'lax'
, but a warning is issued
optional on the constructor with name: interface
object
The actual object with mocked interface. Its gets cached after generation and must be generated again after changing "base".
context
String - name of the method which you are currently testing. Can be utilized if you're currently focusing on a specific method, or have mocked just one. This allows calling "Call history methods" without using an intermediate variable for it.
Can be passed to the constructor or set with the writer. The method does not have to exist during setting its name - the code will throw exception only when you try to actually test it.
optional on the constructor with name: context
writer: set_context
predicate: has_context
clearer: clear_context
General methods
new
Typical Moose-flavored constructor. See property list above for details on hash keys it handles.
add_method
# add a method
my $method = $spy->add_method($name, @returns)
# call it
$spy->object->$name;
Adds a new method with name $name
to the object.
@returns
array is optional and specifies the return value of the new method. If not present, method will return undef
. See "should_return" in Test::Spy::Method for more details.
Return value is an object of Test::Spy::Method.
add_observer
Same as "add_method", but observers don't return and do not interrupt calls to methods of the base object.
Return value is an object of Test::Spy::Observer.
method
my $method = $spy->method($name);
Returns an object of Test::Spy::Method or Test::Spy::Observer that was added with "add_method" or "add_observer" as $name
.
Throws an exception if there is no such method.
clear_all
Calls ->clear
on all registered methods and ->clear_context
. Can be used to run a test again without re-creating the spy.
Call history methods
These methods are also found in Test::Spy::Method's interface. When called on Test::Spy, these methods will execute on the method which name is currently in "context". If there is no context, these methods will throw an exception.
call_history
Returns the entire call history - array reference of array references:
[
# first method call
['first method argument', 'second method argument', ...],
# second method call
['first method argument', 'second method argument', ...],
...
]
This data is very raw, so its often better to use helpers specified below.
called_times
Returns a non-negative integer number - the number of times the method was called.
was_called
Returns a boolean - whether the method was called at least once.
If passed an argument, returns whether the method was called exactly as many times:
$object->method;
$object->method;
$spy->set_context('method');
$spy->was_called; # true
$spy->was_called(1); # false
$spy->was_called(2); # true
$spy->was_called(3); # false
wasnt_called
A shortcut for $spy->was_called(0)
- see above.
was_called_once
A shortcut for $spy->was_called(1)
- see above.
first_called_with
Returns an array reference - the arguments of the first (oldest) method call.
In addition, sets the internal method iterator to the beginning for "next_called_with".
If there were no calls at all, returns undef
.
The behavior of the iterator functions are showcased below:
$object->method(1);
$object->method(2);
$spy->set_context('method');
$spy->first_called_with; # [1]
$spy->called_with; # [1]
$spy->next_called_with; # [2]
$spy->next_called_with; # undef
$spy->last_called_with; # [2]
$object->method(3, 4);
$spy->called_with; # [2]
$spy->next_called_with; # [3, 4]
$spy->first_called_with; # [1]
$object->method;
$spy->last_called_with; # []
next_called_with
Returns an array reference - the arguments of the next (newer) method call.
The internal iterator of the method is increased by 1
as a result.
If there were no more calls, returns undef
.
last_called_with
Returns an array reference - the arguments of the last (newest) method call.
In addition, sets the internal method iterator to the end for "next_called_with".
If there were no calls at all, returns undef
.
called_with
Returns an array reference - the arguments of the current method call. If there was no other X_called_with
call before, acts the same as "first_called_with".
The internal iterator of the method is not altered, unless it was not set at all, in which case it is set to the beginning.
Can return undef
if there was no such call data.
clear
Clears all call and iterator data from the method.
SEE ALSO
AUTHOR
Bartosz Jarzyna <bbrtj.pro@gmail.com>
COPYRIGHT AND LICENSE
Copyright (C) 2022 by Bartosz Jarzyna
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.