Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't mock implementations of abstract methods required by a Moose role #55

Open
DrHyde opened this issue Mar 12, 2021 · 8 comments
Open

Comments

@DrHyde
Copy link
Contributor

DrHyde commented Mar 12, 2021

If you have a Moose class which consumes a role, and that role in turn requires that the class implement a method foo then you can't use Test::MockModule to over-ride the class's implementation. Attempting to do so can result in errors like:

"Invalid implementation class MyApp::SomeClass: 'MyApp::SomeRole' requires the method 'foo' to be implemented by 'Moose::Meta::Class::ANON::SERIAL::8'. If you imported functions intending to use them as methods, you need to explicitly mark them as such, via Moose::Meta::Class::ANON::SERIAL::8->meta->add_method(foo => ..."

As a work-around, instead of doing this in my tests:

my $mockery = Test::MockModule->new('MyApp::Class');
$mockery->mock( foo => sub { 0 });

I am doing this:

MyApp::Class->meta->add_method(totes_not_a_real_sub => sub { 0 });
my $mockery = Test::MockModule->new('MyApp::Class');
$mockery->mock( foo => \&MyApp::Class::totes_not_a_real_sub);

but obviously I'd prefer to have Test::MockModule do the nasty Moose dance for me automagically. Would you accept a patch for that?

@geofffranks
Copy link
Owner

geofffranks commented Mar 12, 2021 via email

@DrHyde
Copy link
Contributor Author

DrHyde commented Mar 24, 2021

FYI I'm having trouble coming up with a small test case without pulling in much of my app's code. There's definitely a problem, but it's unlikely to affect many people.

@DrHyde
Copy link
Contributor Author

DrHyde commented Sep 21, 2021

Note to self, copied from IRC:

09:10 <@.......> including an amusing: package A { sub foo {} } ; package B extends A { around 'foo' => sub {} 
                 }; then use Test::MockModule to mock A::foo, and Class::Load::load_class B - which fails when 
                 it hits the around because it can't find A::foo :D
09:15 < DrHyde> hmmm, i wonder if that's at the root of https://github.com/geofffranks/test-mockmodule/issues/55

@fleetfootmike
Copy link

the above is me, if you want a test case to reproduce...

@DrHyde
Copy link
Contributor Author

DrHyde commented Oct 12, 2021

Yes please @fleetfootmike!

@fleetfootmike
Copy link

fleetfootmike commented Oct 13, 2021

t/mockmodule_around.t

use Test::More tests => 1;
use Test::Exception;
use Test::MockModule;
use Class::Load qw/load_class/;

my $mock = Test::MockModule->new('TestA'); # replace with TestB and it passes
$mock->mock( foo => sub { 3; } );

lives_ok { load_class('TestB'); } "This shouldn't die";

TestA.pm

package TestA;
use Moose;
sub foo { 1; }
1;

TestB.pm

package TestB;
use Moose;
extends 'TestA';
around foo => sub { 2; };
1;
#   Failed test 'This shouldn't die'
#   at t/mockmodule_around.t line 9.
# died: The method 'foo' was not found in the inheritance hierarchy for TestB at /usr/local/lib/perl5/site_perl/5.14.2/x86_64-linux/Class/MOP/Class.pm line 1053.

@XSven
Copy link

XSven commented Apr 15, 2024

... # replace with TestB and it passes

will mock the "around"ed foo in TestB and no longer the foo that belongs to TestA. The same happens if you hinder Test::MockModule to pre-load TestA.

my $mock = Test::MockModule->new('TestA', no_auto => 1);

t/mockmodule_around.t passes.

@XSven
Copy link

XSven commented Apr 15, 2024

Slight correction:

If no_auto is turned on to make the test pass a redefine warning is raised:

prove -v mockmodule_around.t
mockmodule_around.t ..
1..1
Subroutine foo redefined at TestA.pm line 3.
ok 1 - This shouldn't die
ok
All tests successful.
Files=1, Tests=1,  0 wallclock secs ( 0.01 usr  0.01 sys +  0.07 cusr  0.00 csys =  0.09 CPU)
Result: PASS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants