Search code examples
phpstaticmockingphpunitredbean

what is the right way to Unit test business logic with RedBeanPHP ORM


I'm trying to test my business logic that interacts with RedBeanPHP ORM , I don't want to test the RedBeanPHP itself but the behavior of my code when associated with RedBean .

I thought of mocking the method that I wanna test then return the value that I need , in this way I isolate the database connection because I don't need it and I just test the behavior of that method ... The problem however is that all of the methods of RedBean are public static and I have read that I cannot mock such methods .

Note : the call of this method Facade::count('table_name') should return the number of the rows in this table , which is Int.

I tried this test and it does not return Int as I expected it to return :

/**
 * @param string $tableName
 * @param int $returnValue
 *
 * @return \PHPUnit_Framework_MockObject_Builder_InvocationMocker
 */
protected function mockCount($tableName, $returnValue)
{
    $this->beanCount = $this->getMockBuilder(Facade::class)->setMethods(['count'])->getMock();
    return $this->beanCount
        ->expects($this->once())
        ->method('count')
        ->with($this->equalTo($tableName))
        ->willReturn($returnValue);
}

public function testCountSuccess()
{
    $tableCount = $this->mockCount('questions', 7);
    $this->assertInternalType('int', $tableCount);
}

Is there anyway to mock RedBean's static methods ? and if there's is another way or technique that might work in this case ? please advise .

Thank you.


Solution

  • I suggest you to use The Phake mock testing library that support Mocking Static Methods. As Example:

    /**
     * @param string $tableName
     * @param int $returnValue
     *
     * @return \PHPUnit_Framework_MockObject_Builder_InvocationMocker|Facade
     */
    protected function mockCount($tableName, $returnValue)
    {
        $this->beanCount = \Phake::mock(Facade::class);
    
        \Phake::whenStatic($this->beanCount)
            ->count($tableName)
            ->thenReturn($returnValue);
    
        return $this->beanCount;
    }
    
    public function testCountSuccess()
    {
        $tableCount = $this->mockCount('questions', 7);
        $this->assertEquals(7, $tableCount::count('questions'));
    }
    

    Hope this help