Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Test::MockObject(3)   User Contributed Perl Documentation  Test::MockObject(3)

NAME
       Test::MockObject	- Perl extension for emulating troublesome interfaces

SYNOPSIS
	 use Test::MockObject;
	 my $mock = Test::MockObject->new();
	 $mock->set_true( 'somemethod' );
	 ok( $mock->somemethod() );

	 $mock->set_true( 'veritas')
	      ->set_false( 'ficta' )
	      ->set_series( 'amicae', 'Sunny', 'Kylie',	'Bella'	);

DESCRIPTION
       It's a simple program that doesn't use any other	modules, and those are
       easy to test.  More often, testing a program completely means faking up
       input to	another	module,	trying to coax the right output	from something
       you're not supposed to be testing anyway.

       Testing is a lot	easier when you	can control the	entire environment.
       With Test::MockObject, you can get a lot	closer.

       Test::MockObject	allows you to create objects that conform to
       particular interfaces with very little code.  You don't have to
       reimplement the behavior, just the input	and the	output.

   IMPORTANT CAVEATS
       Before you go wild with your testing powers, consider three caveats:

       o   It is possible to write highly detailed unit	tests that pass	even
	   when	your integration tests may fail.  Testing the pieces
	   individually	does not excuse	you from testing the whole thing
	   together.

       o   In cases where you only need	to mock	one or two pieces of an
	   existing module, consider Test::MockObject::Extends instead.

       o   If the code under testing produces strange errors about type
	   checks, pass	the "-debug" flag when using "Test::MockObject"	or
	   "Test::MockObject::Extends".	This will load both UNIVERSAL::isa and
	   UNIVERSAL::can to perform additional	debugging on the incorrect use
	   of both methods from	the UNIVERSAL package. (This behavior used to
	   be active by	default, but that was, however correct,	probably a
	   burden to onerous for the CPAN.)

   EXPORT
       None.

   METHODS
       The most	important thing	a Mock Object can do is	to conform
       sufficiently to an interface.  For example, if you're testing something
       that relies on CGI.pm, you may find it easier to	create a mock object
       that returns controllable results at given times	than to	fake query
       string input.

       The Basics

       o   "new"

	   Creates a new mock object.  By default, this	is a blessed hash.
	   Pass	a reference to bless that reference.

	       my $mock_array  = Test::MockObject->new(	[] );
	       my $mock_scalar = Test::MockObject->new(	\( my $scalar )	);
	       my $mock_code   = Test::MockObject->new(	sub {} );
	       my $mock_glob   = Test::MockObject->new(	\*GLOB );

       Mocking

       Your mock object	is nearly useless if you don't tell it what it's
       mocking.	 This is done by installing methods.  You control the output
       of these	mocked methods.	 In addition, any mocked method	is tracked.
       You can tell not	only what was called, but which	arguments were passed.
       Please note that	you cannot track non-mocked method calls.  They	will
       still be	allowed, though	Test::MockObject will carp() about them.  This
       is considered a feature,	though it may be possible to disable this in
       the future.

       As implied in the example above,	it's possible to chain these calls
       together.  Thanks to a suggestion from the fabulous Piers Cawley	(CPAN
       RT #1249), this feature came about in version 0.09.  Shorter testing
       code is nice!

       o   "mock(name, coderef [, name2, coderef2, ...])"

	   Adds	one or more coderefs to	the object.  This allows code to call
	   the named methods on	the object.  For example, this code:

	       my $mock	= Test::MockObject->new();
	       $mock->mock( 'fluorinate',
		   sub { 'impurifying precious bodily fluids' }	);
	       print $mock->fluorinate;

	   will	print a	helpful	warning	message.  Please note that methods are
	   only	added to a single object at a time and not the class.  (There
	   is no small similarity to the Self programming language or the
	   Class::Prototyped module.)

	   This	method forms the basis for most	of Test::MockObject's testing
	   goodness.

	   Please Note:	this method used to be "add()".	 Due to	its ambiguity,
	   it now has a	different spelling.  For backwards compatibility
	   purposes, add() is available, though	version	0.07 deprecated	it.
	   It goes to some contortions to try to do what you mean, but I make
	   few guarantees.

       o   "fake_module(module name), [	subname	=" coderef, ...	]

	   Note: See Test::MockModule for an alternate (and better) approach.

	   Lies	to Perl	that it	has already loaded a named module.  This is
	   handy when providing	a mockup of a real module if you'd like	to
	   prevent the actual module from interfering with the nice fakery.
	   If you're mocking Regexp::English, say:

	       $mock->fake_module( 'Regexp::English' );

	   This	is both	a class	and as an object method.  Beware that this
	   must	take place before the actual module has	a chance to load.
	   Either wrap it in a BEGIN block before a use	or require or place it
	   before a "use_ok()" or "require_ok()" call.

	   You can optionally add functions to the mocked module by passing
	   them	as name	=> coderef pairs to "fake_module()".  This is handy if
	   you want to test an "import()":

	       my $import;
	       $mock->fake_module(
		   'Regexp::English',
		   import => sub { $import = caller }
	       );
	       use_ok( 'Regexp::Esperanto' );
	       is( $import, 'Regexp::Esperanto',
		   'Regexp::Esperanto should use() Regexp::English' );

	   If you use "fake_module()" to mock a	module that already exists in
	   memory -- one you've	loaded elsewhere perhaps, but do not pass any
	   subroutines to mock,	this method will throw an exception.  This is
	   because if you call the constructor later on, you probably won't
	   get a mock object back and you'll be	confused.

       o   "fake_new(module name)"

	   Note: see Test::MockObject::Extends for a better alternative	to
	   this	method.

	   Provides a fake constructor for the given module that returns the
	   invoking mock object.  Used in conjunction with "fake_module()",
	   you can force the tested unit to work with the mock object instead.

	       $mock->fake_module( 'CGI' );
	       $mock->fake_new(	'CGI' );

	       use_ok( 'Some::Module' );
	       my $s = Some::Module->new();
	       is( $s->{_cgi}, $mock,
		   'new() should create	and store a new	CGI object' );

       o   "set_always(name, value)"

	   Adds	a method of the	specified name that always returns the
	   specified value.

       o   "set_true(name_1, name_2, ... name_n)"

	   Adds	a method of the	specified name that always returns a true
	   value.  This	can take a list	of names.

       o   "set_false(name_1, name_2, ... name_n)"

	   Adds	a method of the	specified name that always returns a false
	   value.  (Since it installs an empty subroutine, the value should be
	   false in both scalar	and list contexts.)  This can take a list of
	   names.

       o   "set_list(name, [ item1, item2, ... ]"

	   Adds	a method that always returns a given list of values.  It takes
	   some	care to	provide	a list and not an array, if that's important
	   to you.

       o   "set_series(name, [ item1, item2, ... ]"

	   Adds	a method that will return the next item	in a series on each
	   call.  This can help	to test	error handling,	by forcing a failure
	   on the first	method call and	then subsequent	successes.  Note that
	   the series does not repeat; it will eventually run out.

       o   "set_bound(name, reference)"

	   Adds	a method bound to a variable.  Pass in a reference to a
	   variable in your test.  When	you change the variable, the return
	   value of the	new method will	change as well.	 This is often handier
	   than	replacing mock methods.

       o   "set_isa( name1, name2, ... namen )"

	   Adds	an apparent parent to the module, so that calling "isa()" on
	   the mock will return	true appropriately.  Sometimes you really need
	   this.

       o   "remove(name)"

	   Removes a named method.

       Checking	Your Mocks

       o   "can( $method_name )"

	   Returns a subroutine	reference if this particular mocked object can
	   handle the named method, false otherwise.

       o   "isa( $class_name )"

	   Returns true	if the invocant	object mocks a particular class.  You
	   must	have used "set_isa()" first.

       o   "called(name)"

	   Checks to see if something has called a named method	on the object.
	   This	returns	a boolean value.  The current implementation does not
	   scale especially well, so use this sparingly	if you need to search
	   through hundreds of calls.

       o   "clear()"

	   Clears the internal record of all method calls on the object.  It's
	   handy to do this every now and then.	 Note that this	does not
	   affect the mocked methods, only all of the methods called on	the
	   object to this point.

	   It's	handy to "clear()" methods in between series of	tests.	That
	   makes it much easier	to call	"next_method()"	without	having to skip
	   over	the calls from the last	set of tests.

       o   "next_call([	position ])"

	   Returns the name and	argument list of the next mocked method	called
	   on an object, in list context.  In scalar context, returns only the
	   method name.	 There are two important things	to know	about this
	   method.  First, it starts at	the beginning of the call list.	 If
	   your	code runs like this:

	       $mock->set_true(	'foo' );
	       $mock->set_true(	'bar' );
	       $mock->set_true(	'baz' );

	       $mock->foo();
	       $mock->bar( 3, 4	);
	       $mock->foo( 1, 2	);

	   Then	you might see output of:

	       my ($name, $args) = $mock->next_call();
	       print "$name (@$args)";

	       # prints	'foo'

	       $name = $mock->next_call();
	       print $name;

	       # prints	'bar'

	       ($name, $args) =	$mock->next_call();
	       print "$name (@$args)";

	       # prints	'foo 1 2'

	   If you provide an optional number as	the position argument, the
	   method will skip that many calls, returning the data	for the	last
	   one skipped.

	       $mock->foo();
	       $mock->bar();
	       $mock->baz();

	       $name = $mock->next_call();
	       print $name;

	       # prints	'foo'

	       $name = $mock->next_call( 2 );
	       print $name

	       # prints	'baz'

	   When	it reaches the end of the list,	it returns undef.  This	is
	   probably the	most convenient	method in the whole module, but	for
	   the sake of completeness and	backwards compatibility	(it takes me a
	   while to reach the truest state of laziness!), there	are several
	   other methods.

       o   "call_pos(position)"

	   Returns the name of the method called on the	object at a specified
	   position.  This is handy if you need	to test	a certain order	of
	   calls.  For example:

	       Some::Function( $mock );
	       is( $mock->call_pos(1),	'setup',
		   'Function() should first call setup()' );
	       is( $mock->call_pos(-1),	'end',
		   '...	and last call end()' );

	   Positions can be positive or	negative.  Please note that the	first
	   position is,	in fact, 1.  (This may change in the future.  I	like
	   it, but am willing to reconsider.)

       o   "call_args(position)"

	   Returns a list of the arguments provided to the method called at
	   the appropriate position.  Following	the test above,	one might say:

	       is( ($mock->call_args(1))[0], $mock,
		   '...	passing	the object to setup()' );
	       is( scalar $mock->call_args(-1),	0,
		   '...	and no args to end()' );

       o   "call_args_pos(call position, argument position)"

	   Returns the argument	at the specified position for the method call
	   at the specified position.  One might rewrite the first test	of the
	   last	example	as:

	       is( $mock->call_args_pos(1, 1), $mock,
		   '...	passing	the object to setup()');

       o   "call_args_string(position, [ separator ])"

	   Returns a stringified version of the	arguments at the specified
	   position.  If no separator is given,	they will not be separated.
	   This	can be used as:

	       is( $mock->call_args_string(1), "$mock initialize",
		   '...	passing	object,	initialize as arguments' );

       o   "called_ok(method name, [ test name ])"

	   Tests to see	whether	a method of the	specified name has been	called
	   on the object.  This	and the	following methods use Test::Builder,
	   so they integrate nicely with a test	suite built around
	   Test::Simple, Test::More, or	anything else compatible:

	       $mock->foo();
	       $mock->called_ok( 'foo' );

	   A generic default test name is provided.

       o   "called_pos_ok(position, method name, [ test	name ])"

	   Tests to see	whether	the named method was called at the specified
	   position.  A	default	test name is provided.

       o   "called_args_pos_is(method position,	argument position, expected, [
	   test	name ])"

	   Tests to see	whether	the argument at	the appropriate	position of
	   the method in the specified position	equals a specified value.  A
	   default, rather non-descript	test name is provided.

       o   "called_args_string_is(method position, separator, expected,	[ test
	   name	])"

	   Joins together all of the arguments to a method at the appropriate
	   position and	matches	against	a specified string.  A generically
	   bland test name is provided by default.  You	can probably do	much
	   better.

       o   "check_class_loaded(	$class_name )"

	   Attempts to determine whether you have a class of the given name
	   loaded and compiled.	 Returns true or false.

       Logging

       Test::MockObject	logs all mocked	methods	by default.  Sometimes you
       don't want to do	this.  To prevent logging all calls to a given method,
       prepend the name	of the method with "-" when mocking it.

       That is:

	   $mock->set_true( '-foo', 'bar' );

       will set	mock both "foo()" and "bar()", causing both to return true.
       However,	the object will	log only calls to "bar()", not "foo()".	 To
       log "foo()" again, merely mock it again without the leading "-":

	   $mock->set_true( 'foo' );

       $mock will log all subsequent calls to "foo()" again.

       Subclassing

       There are two methods provided for subclassing:

       o   "dispatch_mocked_method( $method_name, @_ )"

	   This	method determines how to call a	method (named as $method_name)
	   not available in this class.	 It also controls logging.  You	may or
	   may not find	it useful, but I certainly take	advantage of it	for
	   Test::MockObject::Extends.

       o   "log_call( $method_name, @_ )"

	   This	method tracks the call of the named method and its arguments.

TODO
       o   Add a factory method	to avoid namespace collisions (soon)

       o   Add more useful methods (catch "import()"?)

AUTHOR
       chromatic, <chromatic at	wgz dot	org>

       Thanks go to Curtis 'Ovid' Poe, as well as ONSITE! Technology, Inc.,
       for finding several bugs	and providing several constructive
       suggestions.

       Jay Bonci also found a false positive in	"called_ok()".	Thanks!

       Chris Winters was the first to report I'd accidentally scheduled	0.12
       for deletion without uploading a	newer version.	He also	gave useful
       feedback	on Test::MockObject::Extends.

       Stevan Little provided the impetus and code for "set_isa()".

       Nicholas	Clark found a documentation error.

       Mutant suggested	a potential problem with fake_module().

SEE ALSO
       perl, Test::Tutorial, Test::More,
       http://www.perl.com/pub/a/2001/12/04/testing.html, and
       http://www.perl.com/pub/a/2002/07/10/tmo.html.

COPYRIGHT
       Copyright (c) 2002 - 2016 by chromatic <chromatic at wgz	dot org>.

       This program is free software; you can use, modify, and redistribute it
       under the same terms as Perl 5.24 itself.

       See http://www.perl.com/perl/misc/Artistic.html

perl v5.32.1			  2020-01-22		   Test::MockObject(3)

NAME | SYNOPSIS | DESCRIPTION | TODO | AUTHOR | SEE ALSO | COPYRIGHT

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Test::MockObject&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help