skip to Main Content

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. 🙇🙇🙇🙇

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search