Codeception/AspectMock

test::double not working. Failed asserting that two strings are equal.

mlambley opened this issue · 3 comments

My apologies for the previous issue I logged which was a mess. This time, I have a very specific and hopefully replicable issue.

I've created a brand new laravel project (using 'laravel new'). I then added the following to composer.json:

"codeception/codeception": "*",
"codeception/aspect-mock": "*",

I then ran

composer update && composer install
php artisan make:model UserModel
./vendor/bin/codecept bootstrap

The source code of UserModel is simply

namespace App;

use Illuminate\Database\Eloquent\Model;

class UserModel extends Model
{
    public static function tableName() {
        return "users";
    }
}

I've modified the parent TestCase class as follows:

namespace Tests;

use \Codeception\Test\Unit as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    public function __construct() {
        $this->backupGlobals = false;
        parent::__construct();
    }

    protected function _after() {
        parent::_after();
        \AspectMock\Test::clean();
    }
}

My test class under /tests/Unit uses an example straight from the readme:

namespace Tests\Unit;

use AspectMock\Test as test;
use Tests\TestCase;

class MyTestCase extends TestCase {
    function testTableName() {
        $this->assertEquals('users', \App\UserModel::tableName());
        $userModel = test::double('\App\UserModel', ['tableName' => 'my_users']);
        $this->assertEquals('my_users', \App\UserModel::tableName());
        $userModel->verifyInvoked('tableName');
    }
}

And finally, my /tests/_bootstrap.php file is copied from #10

$loader = require(__DIR__.'/../vendor/autoload.php');
$loader->add('AspectMock', __DIR__ . '/../src');
$loader->add('demo', __DIR__ . '/_data');
$loader->register();
$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
    'cacheDir' => __DIR__.'/_data/cache',
    'includePaths' => [__DIR__.'/_data/demo'],
    'interceptFunctions' => true
]);

Running the code with

./vendor/bin/codecept run

Generates the following output:

There was 1 failure:

---------
1) MyTestCase: Table name
 Test  tests\Unit\MyTest.php:testTableName
Failed asserting that two strings are equal.
- Expected | + Actual
@@ @@
-'my_users'
+'users'
#1  C:\Repos\laratest\tests\Unit\MyTest.php:11
#2  Tests\Unit\MyTestCase->testTableName

So it would seem as though the mock isn't intercepting/replacing the function call. Please advise what I am doing wrong.

I've also tried in _bootstrap.php from the Laravel example in the readme:

$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
    'debug' => true,
    'cacheDir' => 'C:/tmp', //A real folder
    'includePaths' => [__DIR__.'/../vendor/laravel', __DIR__.'/../app']
]);

And various other tweaks. Still not sure what I'm doing wrong.

@mlambley - I found (as you can see from #128) that AspectMock is very sensitive to the way to the autoloader loads code, especially in the area of namespaces. In your example, I believe your UserModel.php code (the system under test) would need to be in the folder /tests/_data according to your posted bootstrap file because of this line:
$loader->add('demo', __DIR__ . '/_data');

If it's not in that folder, that could be why test::double is not working as expected.

This did end up working. Sorry I didn't close the ticket.