Laravel 5.6控制器单元测试编写方法求助(附代码示例)
如何正确为Laravel 5.6的NewOrdersController编写单元测试
看起来你已经迈出了单元测试的第一步,不过你的测试代码里有几个小问题需要修正,同时我们可以完善测试覆盖的场景。下面一步步来解决:
原测试代码中的问题
- 控制器实例化错误:你写的
new newOrder($this->neworders)存在两个问题:一是控制器类名是NewOrdersController而非newOrder;二是你定义的Mock变量是$neworders,不是$this->neworders。 - Mock接口的命名空间缺失:直接写
'NewOrderRepositoryInterface'可能会导致类找不到,最好使用完整的命名空间(比如App\Repositories\NewOrderRepositoryInterface,根据你实际的命名空间调整)。 - 测试场景不完整:你的控制器有两种返回逻辑(订单为空返回0,不为空返回1),原测试只覆盖了一种情况。
- Mock返回值不符合逻辑:原控制器通过
count($orders)判断订单数量,你返回0的话count(0)结果是1,不会触发返回0的分支。
修正后的完整测试代码
use Mockery; use App\Http\Controllers\NewOrdersController; use App\Repositories\NewOrderRepositoryInterface; // 替换成你项目中的实际命名空间 class NewOrderTest extends TestCase { public function tearDown() { Mockery::close(); parent::tearDown(); // 别忘了调用父类的清理逻辑 } /** @test */ public function order_list_returns_0_when_no_orders_exist() { // 1. 创建接口的Mock实例 $newOrdersRepo = Mockery::mock(NewOrderRepositoryInterface::class); // 2. 设置Mock的方法期望:调用getNewOrders一次,返回空数组(触发count为0的分支) $newOrdersRepo->shouldReceive('getNewOrders') ->once() ->andReturn([]); // 3. 实例化控制器并注入Mock依赖 $controller = new NewOrdersController($newOrdersRepo); // 4. 断言返回值符合预期 $this->assertEquals(0, $controller->orderList()); } /** @test */ public function order_list_returns_1_when_orders_exist() { $newOrdersRepo = Mockery::mock(NewOrderRepositoryInterface::class); // 返回非空数组,模拟有订单的情况 $newOrdersRepo->shouldReceive('getNewOrders') ->once() ->andReturn([(object)['id' => 1, 'order_no' => 'ORD-001']]); $controller = new NewOrdersController($newOrdersRepo); $this->assertEquals(1, $controller->orderList()); } }
关键细节说明
- Mock返回值匹配逻辑:原控制器通过
count($orders)判断订单数量,所以模拟无订单时要返回空数组,模拟有订单时返回非空数组,这样才能正确触发对应的分支。 - 命名空间一致性:务必确保
NewOrderRepositoryInterface的命名空间和你项目中的实际文件路径一致,否则会出现类找不到的错误。 - 覆盖所有代码分支:单元测试要覆盖控制器的全部逻辑分支,这样才能验证你的代码在各种场景下都能正常工作。
- 父类清理逻辑:Laravel的
TestCase父类自带测试环境清理逻辑,所以在自定义的tearDown方法里要调用parent::tearDown(),避免测试污染。
内容的提问来源于stack exchange,提问作者Avik Pradhan
相关产品推荐
相关产品推荐

