1
votes

Using Laravel 4.2, I've got a custom class TestyClass in /app/libraries.

Using Mockery and PHPUnit, I am attempting to mock this class, but my Mock doesn't seem to register.

When I run the test, I get Mockery\Exception\InvalidCountException: Method testymethod() from Mockery_0_TestyClass should be called exactly 1 times but called 0 times.

My Controller that I am testing runs TestyClass::testymethod();, and the Log::info inside of testymethod() runs correctly.

What am I missing to register a Mock of a custom class in Laravel 4.2?

$mock = Mockery::mock('TestyClass');
$mock->shouldReceive('testymethod')->once();

TestyClass:

class TestyClass {
    public static function testymethod() {
        Log::info('----=-=-=-=--=in heyhey!@!!=-=-=-=-=-=-=-12312312312312341');
        return true;
    }   
}
3

3 Answers

2
votes

This code:

$mock = Mockery::mock('TestyClass');

Creates a new class that extends TestyClass, adding the behaviour necessary to mock etc, then creates and instance of it and returns it, so $mock is an instance of Mockery_0_TestyClass

You're then telling mockery that you expect that instance to receive a call to the testymethod, but you're actually making a static call to the TestyClass class method. You can do this with mockery, but it's not very good, I wouldn't recommend doing so and you'll probably want to run your tests with process isolation.

$mock = Mockery::mock('alias:TestyClass');
0
votes

Are you calling your controller? There is a difference in testing a class method and testing a controller. If you are testing the controller then try using $this->call - example;

class TestyClassTest extends TestCase {

  public function setUp()
  {
    $this->mock = $this->mock('TestyClass');
  }

  /* Move method to TestCase.php */
  public function mock($class)
  {
    $mock = Mockery::mock($class);
    $this->app->instance($class, $mock);
    return $mock;
  }

  /* Move method to TestCase.php */
  public function tearDown()
  {
    Mockery::close();
  }

  public function testIfTestyControllerRunsTestyMethodAndReturnsOk()
  {
    // Step 3. Arrange
    // Last we arrange our test

    $this->mock->shouldReceive('testymethod')->once();

    // Step 2. Act
    // Then we write how we the results will be asserted.
    // The route should correspond with the controller executing the class method.
    // Eg. TestyMethodController@test; return $this->class->testymethod()

    **$this->call('GET', 'TestyController@test');**

    // Step 1. Assert
    // Start by writing the results we expect;
    // If the controller issues no Exceptions we should get a response header status 200.

    $this->assertResponseOk();
  }
}

Essentially $mock->shouldReceive is setting a listener on the mock object, it is waiting for the method to be run - if it runs then everything is okay, otherwise you get an InvalidCountException.

Hope that helps, have a nice day.

0
votes

I have experienced similar issue: the class was not recognized. Try to use __construct method to initialize it. That worked for me. (It didn't work setting it up in setUp method).

public function __construct()
{
    $this->mock = Mockery::mock('TestyClass');
}

and then just call in test method:

$this->mock->shouldReceive('testymethod')->once();