NAME

Test::Mockify::Sut - injection options for your System under test (Sut) based on Mockify

SYNOPSIS

use Test::Mockify::Sut;
use Test::Mockify::Verify qw ( WasCalled );
use Test::Mockify::Matcher qw ( String );

# build a new system under text
my $MockifySut = Test::Mockify::Sut->new('Package::I::Like::To::Test', []);
$MockifySut->mockImported('Package::Name', 'ImportedFunctionName')->when(String())->thenReturn('Hello');
$MockifySut->mockStatic('Fully::Qualified::FunctionName')->when(String())->thenReturn('Hello');
$MockifySut->mockConstructor('Package::Name', $Object);#  hint: build this object also with Mockify
my $PackageILikeToTest = $MockifySut->getMockObject();

$PackageILikeToTest->do_something();# all injections are used here

# verify that the mocked method were called
ok(WasCalled($PackageILikeToTest, 'ImportedFunctionName'), 'ImportedFunctionName was called');
done_testing();

DESCRIPTION

Use Test::Mockify::Sut to create and configure Sut objects. Use Test::Mockify::Verify to verify the interactions with your mocks.

You can find a Example Project in ExampleProject

METHODS

mockImported

Sometimes it is not possible to inject the dependencies from the outside. This is especially the case when the package uses imports of static functions. mockImported provides the possibility to mock imported functions inside the mock.

Unlike mockStatic is the injection with mockImported only in the mock valid.

synopsis

package Show::Magician;
use Magic::Tools qw ( Rabbit );
sub pullCylinder {
    shift;
    if(Rabbit('white')){
        return 1;
    }else{
        return 0;
    }
}
1;

In the Test it can be mocked

package Test_Magician;
use Magic::Tools qw ( Rabbit );
my $Mockify = Test::Mockify::Sut->new( 'Show::Magician', [] );
$Mockify->mockImported('Magic::Tools','Rabbit')->when(String('white'))->thenReturn(1);

my $Magician = $Mockify->getMockObject();
is($Magician ->pullCylinder(), 1);
Rabbit('white');# return original result
1;

It can be mixed with normal spy

spyImported

spyImported provides the possibility to spy imported functions inside the mock.

Unlike spyStatic is the injection with spyImported only in the mock valid.

synopsis

package Show::Magician;
use Magic::Tools qw ( Rabbit );
sub pullCylinder {
    shift;
    if(Rabbit('white')){
        return 1;
    }else{
        return 0;
    }
}
1;

In the Test it can be mocked

package Test_Magician;
use Magic::Tools qw ( Rabbit );
my $Mockify = Test::Mockify::Sut->new( 'Show::Magician', [] );
$Mockify->spyImported('Magic::Tools','Rabbit')->when(String());

my $Magician = $Mockify->getMockObject();
is($Magician->pullCylinder(), 'SomeValue');
is(GetCallCount($Magician, 'Rabbit'), 1);
1;

It can be mixed with normal spy

mockStatic

Sometimes it is not possible to inject the dependencies from the outside. mockStatic provides the possibility to mock static functions inside the mock.

Attention: The mocked function is valid as long as the $Mockify is defined. If You leave the scope or set the $Mockify to undef the injected method will be released.

synopsis

package Show::Magician;
use Magic::Tools;
sub pullCylinder {
    shift;
    if(Magic::Tools::Rabbit('black')){
        return 1;
    }else{
        return 0;
    }
}
1;

In the Test it can be mocked like:

package Test_Magician;
{ # start scope
    my $Mockify = Test::Mockify::Sut->new( 'Show::Magician', [] );
    $Mockify->mockStatic('Magic::Tools::Rabbit')->when(String('black'))->thenReturn(1);
    $Mockify->spy('log')->when(String());
    my $Magician = $Mockify->getMockObject();

    is($Magician->pullCylinder('black'), 1);
    is(Magic::Tools::Rabbit('black'), 1); 
} # end scope
is(Magic::Tools::Rabbit('black'), 'someValue'); # The orignal method in in place again

It can be mixed with normal spy

ACKNOWLEDGEMENTS Thanks to @dbucky for this amazing idea

spyStatic

Provides the possibility to spy static functions around the mock.

synopsis

package Show::Magician;
sub pullCylinder {
    shift;
    if(Magic::Tools::Rabbit('black')){
        return 1;
    }else{
        return 0;
    }
}
1;

In the Test it can be mocked

package Test_Magician;
use Magic::Tools;
my $Mockify = Test::Mockify::Sut->new( 'Show::Magician', [] );
$Mockify->spyStatic('Magic::Tools::Rabbit')->whenAny();
my $Magician = $Mockify->getMockObject();

$Magician->pullCylinder();
Magic::Tools::Rabbit('black');
is(GetCallCount($Magician, 'Magic::Tools::Rabbit'), 2); # count as long as $Mockify is valid

1;

It can be mixed with normal spy. For more options see, mockStatic

mockConstructor

Sometimes it is not possible to inject the dependencies from the outside. This method gives you the posibility to override the constructor of a package where your Sut depends on. The defaut constructor is new if you need another constructor name, use the third parameter.

Attention: The mocked constructor is valid as long as the Mockify object is defined. If You leave the scope or set the Mockify object to undef the injected constructor will be released.

synopsis

package Path::To::SUT;
use Path::To::Package;
sub callToAction {
    shift;
    return Path::To::Package->new()->doAction();
}
1;

In the Test it can be mocked like:

package Test_SUT;
{ # start scope
    my $MockifySut = Test::Mockify::Sut->new( 'Path::To::SUT', [] );
    $MockifySut->mockConstructor('Path::To::Package', $self->_createPathToPackage()); 
    my $Test_SUT = $MockifySut->getMockObject();

    is($Test_SUT->callToAction(), 'hello');
} # end scope

sub _createPathToPackage{
    my $self = shift;
    my $Mockify = Test::Mockify::Sut->new( 'Path::To::Package', [] );
    $Mockify->mock('doAction')->when()->thenReturn('hello');
    return $Mockify->getMockObject();
}

It can be mixed with normal spy.

getVerificationObject

Provides the actual mock object, which you can use for verification. This is code sugar for the method getMockObject.

my $Mockify = Test::Mockify::Sut->new( 'My::Module', [] );
my $VerificationObject = $Mockify->getVerificationObject();
ok(WasCalled($VerificationObject, 'FunctionName'));