如何在Lumen中使用mock

时间:2018-04-04 02:20:05

标签: php phpunit mockery

如何在流明框架中使用mock? 我使用Lumen框架。流明文件非常简单。我不知道如何使用嘲弄或外墙来模拟模型。我尝试了一些方法,但没有人工作。我想在 updatePassword 方法中模拟两点 UserModel 。 请帮帮我。

的usermodel

use Illuminate\Database\Eloquent\Model;
class UserModel extends Model {
    // connection
    protected $connection = 'db_user';
    // table
    protected $table = 'user';
    // primarykey
    protected $primaryKey = 'id';
}

UserLogic

class UserLogic {
    public static updatePassword($id, $password) {
        // find user
        $user = UserModel::find($id); // mock here**************************************
        if (empty($user)) {
            return 'not find user';
        }
        // update password
        $res = UserModel::where('id', $id)
               ->update(['password' => $password]); // mock here*****************************
        if (false == $res) {
            return 'update failed';
        }
        // re Login
        $res2 = LoginModel::clearSession();
        if (false == $res2) {
            return false;
        }
        return true;
    }
}

phpunit test 1不起作用

use Mockery;
public function testUpdatePassword() {
    $mock = Mockery:mock('db_user');
    $mock->shouldReceive('find')->andReturn(false);
    $res = UserLogic::updatePassword(1, '123456');
    $this->assertEquals('not find user', $res);
}

phpunit test 2

// BadMethodCallException: Method Mockery_0_Illuminate_DatabaseManager::connection() does not exist on this mock object
use Illuminate\Support\Facades\DB;
public function testUpdatePassword() {
    DB::shouldReceive('select')->andReturnNull();
    $res = UserLogic::updatePassword(1, '123456');
    $this->assertEquals('not find user', $res);
}

phpunit test 3不起作用

use Mockery;
public function testUpdatePassword() {
    $mock = Mockery::mock('alias:UserModel');
    $mock->shouldReceive('find')->andReturn(null);
    $res = UserLogic::updatePassword(1, '123456');
    $this->assertEquals('not find user', $res);
}

1 个答案:

答案 0 :(得分:0)

尝试一下:

    $mock = Mockery::mock('alias:\NamespacePath\To\UserModel');
    $mock->shouldReceive('find')->andReturn(null);
    $this->app->instance('\NamespacePath\To\UserModel', $mock);

请注意,当您要模拟公共静态函数时,请使用关键字alias。如果要模拟对象(使用new创建),请改用关键字overloadWhat is the difference between overload and alias in Mockery?)。

我面对模拟的另一个困难是,我们仍将它们用于其他测试中,在这些测试中我不再想要使用模拟,这使测试失败。模拟持久性与类的加载有关。这种情况只在全局范围内发生一次,一直持续到测试过程终止(从此处:https://blog.gougousis.net/mocking-static-methods-with-mockery/)开始。因此,首先出现的任何事情(将类用作模拟或真实事物)都将定义该类的调用方式,之后您将无法再对其进行更改。在我之前链接的几篇博客文章中,Alexandros Gougousis讨论了如何通过在自己的进程中运行模拟测试并禁用全局状态保存来避免此问题。我尝试了他的方法,但遇到了一些问题,但我也没有花费太多时间。为什么不?因为我找到了不同的解决方案,所以:在phpunit.xml中设置变量processIsolation="true"。这样就解决了问题。我应该注意,这使每次测试的持续时间增加了大约20%。 0.5s,因此Alexandros方法可能会更有效,因为它只能在其自己的进程中运行带有模拟的测试。

侧面说明:这也与Lumen TestCase一起用作测试的基类。