【问题标题】:Mocking a service class inside controller在控制器内模拟服务类
【发布时间】:2021-04-25 16:02:39
【问题描述】:

我正在尝试为我的控制器编写功能测试。为了简化我目前的情况,想象一下我的控制器是这样的:

public function store(Business $business)
{
   try {
      (new CreateApplicationAction())->execute($business);
   } catch (Exception $e) {
      return response()->json(['message' => 'error'], 500);
   }

   return response()->json(['message' => 'success']);
}

我想要实现的是,我不想在集成测试中测试 CreateApplication 类逻辑,而是专门为它编写另一个单元测试。

有没有办法我可以简单地说 CreateApplicationAction 期望 execute() 并绕过其中的测试? (不执行execute()里面的代码)

/** @test */
public function can_create_application()
{
    $business = Business:factory()->create();

    $mock = $this->mock(CreateApplicationAction::class, function (MockInterface $mock) use ($business) {
         $mock->shouldReceive('execute')
             ->once()
             ->with($business)
             ->andReturn(true);
    });

    $response = $this->post('/businesses/3/application', $data);

    $response->assertOk();
}

我在网上看到人们创建“MockCreateApplicationAction”类,但如果可能的话,我不想创建另一个类,因为我根本不希望在其中包含任何逻辑。

有可能吗?

class CreateApplicationAction
{
    public function execute($business) {
        dd("A");

        // Business Logic...
    }
}

所以当我做 Mock 时,永远不应该调用 dd()。还是我走错了方向?

【问题讨论】:

    标签: laravel testing mocking laravel-8


    【解决方案1】:

    您需要使用Laravels 容器来解析您的课程。基本方法是使用resolve() 方法助手。 PHP 没有依赖注入,所以你需要使用一个来使它成为可能,在Laravel 容器解决了这个问题。

    resolve(CreateApplicationAction::class)->execute($business);
    

    在构造函数、控制器方法、作业、事件、侦听器和命令(如果方法名为句柄),您可以将类注入参数,它们将通过容器解析。

    public function store(Business $business, CreateApplicationAction $applicationAction)
    {
        try {
            $applicationAction->execute($business);
      
    

    【讨论】:

      猜你喜欢
      • 2014-01-16
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 2019-06-20
      • 2020-04-02
      • 1970-01-01
      相关资源
      最近更新 更多