stringContains argument matching within Laravel Log facade shouldReceive
Asked Answered
T

1

2

I saw in the Laravel docs that it's possible to set a test expectation like this:

Cache::shouldReceive('get')
                ->once()
                ->with('key')
                ->andReturn('value');

Then I saw in the PHPunit docs that flexible argument matching is possible like this: $this->stringContains('Something').

But when I edit my test to have this:

Log::shouldReceive('error')
            ->once();
            ->with($this->stringContains('Contact does not exist'));

...then I get the following error:

Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_1_Illuminate_Log_Writer::error("Contact does not exist blah blah etc"). 
Either the method was unexpected or its arguments matched no expected argument list for this method

How can I accomplish my goal (with flexible argument matching within Log::shouldReceive)?

P.S. I've also tried ->with(\PHPUnit\Framework\Assert::stringContains('Contact does not exist')).

Trichology answered 25/10, 2017 at 0:8 Comment(0)
E
5

The mocking functionality of facades uses Mockery to generate mock objects. stringContains() is functionality provided by PHPUnit mock objects. These two are not compatible.

You will need to use argument validation methods provided by Mockery.

My first attempt would be to use the \Mockery::pattern() matcher which uses regular expressions:

Log::shouldReceive('error')
    ->once()
    ->with(\Mockery::pattern('/Contact does not exist/'));

Another option would be to use the \Mockery::on() matcher, which allows you to use a Closure to provide complex argument matching logic.

Log::shouldReceive('error')
    ->once()
    ->with(\Mockery::on(function ($arg) {
        return stripos($arg, 'Contact does not exist') !== false;
    }));
Etheridge answered 25/10, 2017 at 1:8 Comment(6)
Wow, I love it. Thanks so much!Trichology
Your link to argument validation helped in my case, as it was Mockery::withArgs() I needed to perform validation for multiple arguments. ThanksKaycekaycee
This helped me again just now. Thanks. I couldn't get \Mockery::pattern() working, but \Mockery::on() does.Trichology
Wow, I keep coming back to this answer and wish either I could commit this to memory or that many more articles would link here.Trichology
I am getting Mockery::pattern() method not found error. Any ideas? There are other assertions that use Mockery::any() and they all seem to work fine.Drambuie
@Drambuie The pattern() method was added in version 1.0. If you're using version 0.9.11 or below, the pattern() method will not exist.Etheridge

© 2022 - 2024 — McMap. All rights reserved.