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

with_deep tests failing when references are modified after test call is made #52

Open
cblake777 opened this issue Mar 9, 2022 · 0 comments

Comments

@cblake777
Copy link

Working through some tests today, came across this issue with with_deep tests.

When mocking a call being made within a method being tested, the test was failing because there were "extra keys" within the hash ref being checked, even though we could prove those keys were not there. Essentially, it looks like when _given_args is called, and the args sent contain a hash ref or array ref, those references are being stored directly, instead of a clone of the data at the time the call is made. Those references are then used when the check is run, but by that time, the references have been updated with additional data.

A sample test written to demonstrate the problem:

#!/usr/local/bin/lwperl
use Test::Spec;
use Data::Dumper qw/Dumper/;

describe "Testing 'with_deep' values" => sub {
	my ($mock, $fiddle);
	before each => sub {
		$mock = mock();
		$fiddle = sub {
			my ($hash1, $hash2) = @_;
			$mock->foo($hash1, $hash2);
			$hash1->{blah} = 9;
			$hash2->{count} = 1;
			$hash2->{faddle} = 2;
			return;
		};
	};
	it "should pass, at the time 'foo' was called, hash1 and hash2 are correct" => sub {
		my $hash1 = { big => 1 };
		my $hash2 = { bat => 2 };
		my $expect = $mock->expects('foo')
			->with_deep({ big => 1 }, {bat => 2})
			->returns(sub { print 'Values when foo was called => ' . Dumper(\@_) });
		$fiddle->($hash1, $hash2);
		ok($expect->verify);
	};
	it "should pass, at the time 'foo' was called, hash1 and hash2 are correct" => sub {
		my $hash1 = { big => 1, blah => 9 };
		my $hash2 = { bat => 2 };
		my $expect = $mock->expects('foo')
			->with_deep({ big => 1, blah => 9}, {bat => 2})
			->returns(sub { print 'Values when foo was called => ' . Dumper(\@_) });
		$fiddle->($hash1, $hash2);
		ok($expect->verify);
	};
	it "SHOULD DEFINITELY FAIL, at the time 'foo' was called, hash1 and hash2 are not correct" => sub {
		my $hash1 = { big => 1 };
		my $hash2 = { bat => 2 };
		my $expect = $mock->expects('foo')
			->with_deep({ big => 1, blah => 9}, {bat => 2, count => 1, faddle => 2})
			->returns(sub { print 'Values when foo was called => ' . Dumper(\@_) });
		$fiddle->($hash1, $hash2);
		ok($expect->verify);
	};
};

runtests unless caller;

The output of the test is as follows:

---- start of test 1 ----
Values when foo was called => $VAR1 = [
          bless( {}, 'Test::Spec::Mocks::MockObject' ),
          {
            'big' => 1
          },
          {
            'bat' => 2
          }
        ];
not ok 1 - Testing 'with_deep' values should pass, at the time 'foo' was called, hash1 and hash2 are correct


#   Failed test 'Testing 'with_deep' values should pass, at the time 'foo' was called, hash1 and hash2 are correct' by dying:
#     Comparing hash keys of $data->[0][0]
Extra: 'blah'

Comparing hash keys of $data->[0][0]
Extra: 'blah'

---- start of test 2 ----
Values when foo was called => $VAR1 = [
          bless( {}, 'Test::Spec::Mocks::MockObject' ),
          {
            'big' => 1,
            'blah' => 9
          },
          {
            'bat' => 2
          }
        ];
not ok 2 - Testing 'with_deep' values should pass, at the time 'foo' was called, hash1 and hash2 are correct


#   Failed test 'Testing 'with_deep' values should pass, at the time 'foo' was called, hash1 and hash2 are correct' by dying:
#     Comparing hash keys of $data->[0][1]
Extra: 'count', 'faddle'

Comparing hash keys of $data->[0][1]
Extra: 'count', 'faddle'

---- start of test 3 ----
Values when foo was called => $VAR1 = [
          bless( {}, 'Test::Spec::Mocks::MockObject' ),
          {
            'big' => 1
          },
          {
            'bat' => 2
          }
        ];
ok 3 - Testing 'with_deep' values SHOULD DEFINITELY FAIL, at the time 'foo' was called, hash1 and hash2 are not correct
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

1 participant