如何在Laravel中的测试控制器中模拟其他类函数

时间:2019-07-18 14:56:52

标签: laravel mocking integration-testing

我正在尝试在Laravel中测试一个控制器,该控制器使用另一个类作为调用API并返回结果的辅助类。

为避免外部API调用,我需要模拟此帮助程序。

我试图在控制器内部模拟该类并运行测试,但没有得到模拟类所期望的结果。

这是我的控制器方法:

public function A(Request $request){
  $helper = new TheHelper();
  $result = $helper->getResult($request->email);
  if($result){
    return response()->json([
                'success' => true,
                'message' => "result found",
            ], 200);  
  }else{
    return response()->json([
                'success' => false,
                'message' => "no result",
            ], 500);
  }

}

我的助手方法只是调用一个API并返回结果。

class TheHelper
{
    public function getResult($email){
      // some api calls
      return $result;
    }
}

这是我的考试:

public function testExample()
    {

        $helperMock = Mockery::mock(TheHelper::class);

        // Set expectations
        $helperMock ->shouldReceive('getResult')
            ->once()
            ->with('testemail@test.com')
            ->andReturn([
                'id' => '100'
            ]);

        $this->app->instance(TheHelper::class, $helperMock);

        $this->json(
            'POST',
            '/api/test_method',
            ['email' => 'testemail@test.com'])
            ->assertStatus(200);
}

我的模拟函数从未调用过。它只检查TheHelper方法中的真实API

1 个答案:

答案 0 :(得分:1)

您的测试是创建一个模拟对象并将该模拟对象绑定到Laravel服务容器中。但是,您的控制器没有从Laravel服务容器中提取TheHelper实例;它是使用new关键字手动实例化的。使用new关键字是PHP的核心,完全不涉及Laravel。

您的测试正在向您显示代码中的问题。 TheHelper是您方法的依赖项,因此应传递到方法中,而不是在方法内部创建。

您需要更新控制器方法以使用依赖项注入,以便Laravel可以从其容器中自动解决TheHelper依赖项,或者您需要将new关键字替换为对Laravel容器。

使用依赖注入:

public function A(Request $request, TheHelper $helper)
{
    $result = $helper->getResult($request->email);
    // rest of function...
}

手动从容器中拉出:

public function A(Request $request)
{
    $helper = app(TheHelper::class);
    $result = $helper->getResult($request->email);
    // rest of function...
}