Laravel Post请求测试断言方法报错及无断言警告问题咨询
Laravel API测试问题:POST请求断言报错/无断言警告
问题描述
我是Laravel框架测试新手,在测试API的POST端点时,使用assertOk()、assertStatus()等断言方法会报错;但去掉断言后,测试又会出现“未执行任何断言”的警告。
测试代码
<?php namespace Tests\Feature; use Illuminate\Http\Response; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Request; use Symfony\Component\HttpFoundation\Response as HttpResponse; use Tests\TestCase; class LocationTest extends TestCase { /** * A basic feature test example. * * @return void */ public function test_get_all_report() { Http::fake([ 'http://127.0.0.1:8000/*' => Http::response([ [ "latitude"=> "1.56786467", "longitude"=> "-0.056789685", "message"=> "test test that's a place of risk" ], [ "latitude"=> "1.56786467", "longitude"=> "-0.056789685", "message"=> "test test that's a place of risk" ] ], 200), ]); $response = $this->getJson('api/get-all-signal-zone')->assertStatus(200); } /** * A basic feature test example. * * @return void */ public function test_get_all_report_catch_error() { Http::fake([ 'http://127.0.0.1:8000/*' => Http::response([ [ "message"=> "Server error" ] ], 500), ]); $response = $this->getJson('api/get-all-signal-zone')->assertStatus(Response::HTTP_INTERNAL_SERVER_ERROR); } /** * A basic feature test example. * * @return void */ public function test_get_all_report_by_date() { Http::fake(); $response = Http::post('http://127.0.0.1:8000/api/get-all-signal-zone-by-date', [ "date"=> "2022-11-10" ]); } }
路由文件
<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\LocationController; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); }); Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); }); Route::get('/get-all-signal-zone', [LocationController::class, 'all']); // Route::get('/get-all-signal-zone-by-date/{date}', [LocationController::class, 'getLocationByDate'])->name('reporting_by_date'); Route::post('/get-all-signal-zone-by-date', [LocationController::class, 'getLocationByDate']); Route::post('/send-signal-zone', [LocationController::class, 'save']);
控制器代码
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Repositories\Location\LocationRepository; /** * Description of LocationController * * @author Amoungui */ class LocationController extends Controller { public function __construct(LocationRepository $locationRepository) { $this->locationRepository = $locationRepository; } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function all(){ return $this->locationRepository->list(); } /** * View a list of the resource based on a date. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function getLocationByDate(Request $request){ return $this->locationRepository->getByDate($request->date); } /** * Save a newly created resource in external api. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function save(Request $request){ $response = $this->locationRepository->store($request->all()); if($response->successful()){ return response()->json([ 'status' => true, 'message' => "location submited successfully", 'data' => $request->all() ], 201); } return response()->json([ 'data' => null, 'message' => 'Failed', ], 500); } }
测试报错信息
WARN Tests\Feature\LocationTest
✓ get all report
✓ get all report catch error
! get all report by date → This test did not perform any assertions C:\wamp64\www\backend-11-user-story-reporting-of-a-place-in-danger\tests\Feature\LocationTest.php:61Tests: 1 risky, 4 passed
Time: 0.64s
解决方案
核心问题
你的POST测试用错了方法:
Http::post()是Laravel用于在应用代码中发起外部HTTP请求的工具,返回的是Illuminate\Http\Client\Response对象,它不支持assertStatus()这类测试断言方法,所以加断言会报错。- 测试自己的API端点,必须用测试类提供的
$this->postJson()方法,它返回的Illuminate\Testing\TestResponse对象支持所有Laravel测试断言。 - 你之前fake自己的API地址完全没必要——
Http::fake()是用来模拟控制器/仓库层调用的外部API,而非自己的API。
修改后的POST测试代码
public function test_get_all_report_by_date() { // 若你的LocationRepository::getByDate()调用了外部API,在此fake该外部接口的响应 Http::fake([ // 替换为仓库实际调用的外部API地址规则 'your-external-api.com/*' => Http::response([ [ "latitude"=> "1.56786467", "longitude"=> "-0.056789685", "message"=> "test test that's a place of risk" ] ], 200), ]); // 用$this->postJson()测试自身API端点 $response = $this->postJson('api/get-all-signal-zone-by-date', [ "date" => "2022-11-10" ]); // 添加断言,解决无断言警告并验证API响应 $response->assertStatus(200); // 可根据需求添加更多断言,比如验证返回的JSON结构 // $response->assertJsonStructure([ // '*' => ['latitude', 'longitude', 'message'] // ]); }
额外说明
- 如果
getByDate()方法没有调用外部API,完全不需要Http::fake(),直接调用$this->postJson()并添加断言即可。 - 所有测试自身API的场景,都应使用
$this->getJson()、$this->postJson()等测试方法,而非Http::*系列方法。
内容的提问来源于stack exchange,提问作者Serge
相关产品推荐
相关产品推荐

