I'm writing a new module called Test::MockObject. It has a test that reads:
$mock->add('foo');
can_ok( $mock, 'foo' );
Test::MockObject has a custom can() method, which checks instance data to decide if
the object can handle the method:
sub can {
my ($self, $sub) = @_;
return exists $self->{_subs}{$sub};
}
Attached is a patch to make Test::More do the right thing (as I see it) in this
case. Previously, it called can() on the class name, which obviously doesn't
work here.
I suspect something similar should be done for isa_ok().
The included test fails with vanilla 0.43 and passes with the attached patch.
Maybe it would be better to bless a scalar,
-- c
--- lib/Test/More.old Sat Apr 20 11:29:07 2002
+++ lib/Test/More.pm Sat Apr 20 11:44:56 2002
@@ -454,21 +454,21 @@
=cut
sub can_ok ($@) {
- my($proto, @methods) = @_;
- my $class= ref $proto || $proto;
+ my($class, @methods) = @_;
unless( @methods ) {
my $ok = $Test->ok( 0, "$class->can(...)" );
$Test->diag(' can_ok() called with no methods');
return $ok;
}
+ my $can_test = ref( $class ) ?
+ sub { $class->can($_[0]) } : sub { eval "$class->can('$_[0]')" };
my @nok = ();
foreach my $method (@methods) {
- my $test = "'$class'->can('$method')";
local($!, $@); # don't interfere with caller's $@
# eval sometimes resets $!
- eval $test || push @nok, $method;
+ eval { $can_test->($method) } || push @nok, $method;
}
my $name;
--- t/More.old Sat Apr 20 11:29:25 2002
+++ t/More.t Sat Apr 20 11:44:58 2002
@@ -7,7 +7,7 @@
}
}
-use Test::More tests => 37;
+use Test::More tests => 39;
# Make sure we don't mess with $@ or $!. Test at bottom.
my $Err = "this should not be touched";
@@ -38,10 +38,19 @@
can_ok(bless({}, "Test::More"), qw(require_ok use_ok ok is isnt like skip
can_ok pass fail eq_array eq_hash eq_set));
+# can_ok() should call can() on object, not just class, in case of custom can()
+{
+ local *Foo::can;
+ *Foo::can = sub { $_[0]->[0] };
+ my $foo = bless([0], 'Foo');
+ ok( ! $foo->can('bar') );
+ $foo->[0] = 1;
+ can_ok( $foo, 'blah');
+}
+
isa_ok(bless([], "Foo"), "Foo");
isa_ok([], 'ARRAY');
isa_ok(\42, 'SCALAR');
-
pass('pass() passed');