VolkswagenLov
VolkswagenLov

Reputation: 1

PhpUnit test use Mockery - Bypass exception of method from another class

I have a laravel project and I got a problem with using PhpUnit test use Mockery. This is the fist time I use Mockery.

Below, I have some pseudo code:

class Mail
{
   public static function send($pin){ 
     // Perform send mail
     
     // This is fake current excetion
     throw new exception('Send mail error');
   }
}

class CompanyService
{
  
   public function providePin($pin)
   {
      try {
          // send mail but got exception
          Mail::send($pin);
          return true;
       }catch(\Exception $e) {
          // Write error to log file
          return false;
       }
   }

   
}

I have a test class below and I tried to bypass the exception in Mail::send($pin) but It's not working.

// I have a test class
class CompanyTest
{
   public function testProvidePin()
   {
      $mock = Mockery::mock(CompanyService::class)->makePartial();
      $res = $mock->shouldReceive('providePin')->with(300386)->times(1)->andReturn(true);
      // But everytime I got `false` at this
      $this->assertTrue($res);
   }
}

So, How can I bypass the exception in Mail::send($pin) ?

Thank for your help. 🙇🙇🙇🙇

Upvotes: -1

Views: 66

Answers (2)

matiaslauriti
matiaslauriti

Reputation: 8082

I will leave this as an answer instead of a comment because if it is your case, it will already solve your issue:

So, if your Mail class is a Facade in your real code, then you don't even need Mockery at all (no need to initialize it). There is a dedicated section in the Laravel's documentation about testing Facades.

If it is a Facade, your test code should be like this:

class CompanyTest
{
    public function testProvidePin()
    {
        CompanyService::shouldReceive('providePin')
            ->with(300386)->times(1)->andReturn(true);

        // Execute your real code

        // Assert something
    }
}

On my experience, you should never create pure static classes, because you cannot mock them, so either use a normal class that you have to initialize, or just declare them as a Facade (have in mind that they are a Singleton), so it is super easy to mock or spy them.

Upvotes: 1

Amade
Amade

Reputation: 3968

If your test resembles the pseudocode, then you're missing the call:

Mail::send($pin);

before:

$this->assertTrue($res);

in your test.

Try to put dd($res); before $this->assertTrue($res); to see what I mean:

You're trying to assert that "Mockery Expectation" object is boolean true, which fails the test. With Mockery, you're just setting up the test expectations: what should happen when certain method gets called. But you still need to make sure that that method does get called.

Upvotes: 1

Related Questions