如何为控制器编写可测试的代码



我写了一个laravel代码,我很沮丧,因为我认为我写的都是糟糕的代码,无法测试。我会发布我的代码。

正如你们所看到的,我直接在控制器中使用模型。但我只需要知道如何编写灵活可测试的laravel控制器代码的最佳方法。在我看来,我在这里展示的代码似乎太不稳定了。你觉得怎么样?

这是我的控制器:

class AuthController extends Controller
{
protected $auth;
protected $notification;
public function __construct(AuthHelper $auth, NotificationHelper $notification){
$this->auth = $auth;
$this->notification = $notification;
}

public function loginUser(UserLoginRequest $request){
$credentials = $request->only('email', 'password');
return $this->auth->generateJwtAndRefreshToken($credentials);
}

public function registerUser(UserRegisterRequest $request){
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->password =  Hash::make($request->password);
$user->country_id = $request->country_id;
$user->phone = $request->phone;
$user->address = $request->address;
return $this->auth->registerUserHelper($request, $user, $this->notification);
}
}

这是我的助手类

<?php
namespace AppHttpHelpers;
use TymonJWTAuthFacadesJWTAuth;
use AppHttpModelsUsersUser;
use AppHttpModelsUsersTokenUser;
use AppHttpHelpersNotificationHelper;
use AppHttpModelsUsersEmailConfirmation;
use AppHttpModelsUsersPasswordResetConfirmation;
use AppHttpModelsPermissionsRole;
use CarbonCarbon;
use DB;
class AuthHelper {
// generates guuid which will be called refresh token.
public function generateRefreshToken(){
mt_srand((double)microtime()*10000); //optional for php 4.2.0 and up.
$charid = strtoupper(md5(uniqid(rand(), true)));
$hyphen = chr(45);// "-"
$uuid = substr($charid, 0, 8).$hyphen
.substr($charid, 8, 4).$hyphen
.substr($charid,12, 4).$hyphen
.substr($charid,16, 4).$hyphen
.substr($charid,20,12);
return  $uuid;
}

/* generates access and refresh token while logging a user */
public function generateJwtAndRefreshToken($credentials){
try {
if (! $access_token = JWTAuth::attempt($credentials)) {
return response()->json(['message' => trans("errors.user_not_exists")], 404);
}
} catch (JWTException $e) {
return response()->json(['message' => trans("errors.500")], 500);
}
$refresh_token = $this->generateRefreshToken();
$user = JWTAuth::user();
$refreshTokenUser = TokenUser::updateOrCreate(
['user_id' => $user->id],
['refresh_token' => $refresh_token, 'expiration_date' => Carbon::now()->addMinutes(Config::get("jwt.refresh_token_expiration"))]
);
if(!$refreshTokenUser){
return response()->json(['message' => trans("errors.500") ], 500);
}
return response()->json([ 
'access_token' => $access_token,
'refresh_token' => $refresh_token
], 200);
}

public function registerUserHelper($request, $user, $notification){
$confirmation_code = str_random(6);
DB::beginTransaction();
try{
$role_id = Role::where("name", $request->role_name)->first()->id;
EmailConfirmation::create([
'code' => $confirmation_code, 
'email' => $request->email, 
'expires_at' => Carbon::now()->addHour()
]);
$user->save();
$user->roles()->attach($role_id);
$userTokens  = $this->generateJwtAndRefreshToken($request->only("email", "password"));
if($userTokens->status() != 200) throw new Exception();
DB::commit();
}catch(Exception $e){
DB::rollback();
return response()->json(['message'=> trans('errors.500')],500); 
}
$notification->sendMail(['to' => $request->email, 'template_name' =>'RegisterVerification', 'confirmation' => $confirmation_code]);
return response()->json(['message'=> trans('errors.registered'),'user_token' => $userTokens->getOriginalContent()], 200); 
}

为此,我建议您使用两种模式。

  1. Repository模式,它可以帮助您在模型和模型客户端之间创建一个层。所以,所有的东西都将从存储库访问,而不是模型和模型将用于编写每个存储库。https://medium.com/employbl/use-the-repository-design-pattern-in-a-laravel-application-13f0b46a3dce这个链接可以让您更清楚地了解存储库模式。

  2. 服务层,这将是一个包含所有业务逻辑类作为服务的层。最终,您将使用控制器中的服务。https://m.dotdev.co/design-pattern-service-layer-with-laravel-5-740ff0a7b65f这可以澄清服务层。

基本上,服务使用存储库进行所有数据库交互,而不是直接在控制器中进行交互。

最新更新