我如何模拟 `Dingo\Api\Auth\Provider\JWT` 以便在对端点进行单元测试时绕过身份验证开销?

How I can mock `Dingo\Api\Auth\Provider\JWT` so I can bypass the Authentication overhwad whilst I am unit testing my endpoints?

我在 api 中使用 dingo/api,我想对端点进行单元测试:


class MyApiTest extends TestCase
{
  public function testEndpoint()
  {
     $dispatcher = app('Dingo\Api\Dispatcher');
     $fake_token = 'cndksjonsdcnsod';
     $dispatcher->header('Authorization', 'Bearer: '.$fake_token);

     $dispatcher->version($version)->get('/my-endpoint');
  }
}

在我的 app.php 中,我有以下配置:

    'auth' => [
        'jwt' => Dingo\Api\Auth\Provider\JWT::class,
    ],

有没有办法 mock/fake/set 默认值到 Dingo\Api\Auth\Provider\JWT jwt 身份验证提供程序?

一种对我有用的方法是通过绕过 Dingo 和路由本身使用的任何中间件来测试控制器本身和模拟 JWT 身份验证服务。

示例:

假设我们有以下控制器:


use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Tymon\JWTAuth\Facades\JWTAuth;


class ProfileController extends Controller
{

  public function getProfile(Request $request,$profile_id)
  {
      $user     = JWTAuth::parseToken()->authenticate();
      $language = App::getLocale();
      // Do stuff Here
  }
}

你可以写一个简单的测试:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Tymon\JWTAuth\Facades\JWTAuth;

// Set a test class for speed is ommited

public function testMyApiCall()
{
  /**
   * $user is an instance of a User
   */
  JWTAuth::shouldReceive('parseToken->authenticate')->andReturn($user);
  App::setlocale('el');
  
  $request  = new Request();
  $request->initialize([],['token' => 'AAABBBCCC' ],[],[],[],[],[]);
  
  $controller = new ProfileController();

  // I ommit the profile_id value it is just a demonstration
  $response = $controller->getProfile($request,$profile_id)
  
  $response_dody = $response->getData(false);

  // Perform assertions upon $response_dody 
}

在我们的例子中,我们不关心使用什么路由以及它是如何设置的。因此,在这个例子中没有提到任何路由和任何关于 Dingo 的东西,我们只是忘记它。

优缺点

虽然它不是灵丹妙药,但它是一种可以提供专注于实际代码的可靠结果的方法。请记住,尽管您绕过了许多您可能也想测试的中间件,例如。认证的。

另一方面,您可以测试控制器内部的逻辑,如果逻辑相当小而无法为其创建单独的 class/method,例如。从数据库中选择数据。