【问题标题】:How to test validation errors throw exact error and message in laravel unit tests如何测试验证错误在 laravel 单元测试中抛出确切的错误和消息
【发布时间】:2017-08-19 21:15:53
【问题描述】:

如何测试验证错误中抛出的php单元中的特定验证错误? 使用下面的代码,我们可以检查会话是否有错误,但不是确切的错误

$this->assertSessionHasErrors();

【问题讨论】:

  • > 我正在使用 phpunit 7.5 和 Lumen 5.8 - 当对您的 Request 或规则使用单元测试时,您可以执行 $this->expectException$this->expectException('Illuminate\Validation\ValidationException');$this->expectExceptionMessage = "The name field is required"; - 另请参阅 stackoverflow.com/questions/18647836/…跨度>
  • 注意:异常不包含验证信息!它只是说The given data was invalid

标签: php unit-testing laravel-5 phpunit tdd


【解决方案1】:

找到答案

    $errors = session('errors');
    $this->assertSessionHasErrors();
    $this->assertEquals($errors->get('name')[0],"Your error message for validation");

$errors 是 MessageBag 对象,在抛出验证错误时存储在 laravel 会话中 使用 $errors->get('name') 你可以看到所有的验证错误作为一个数组

【讨论】:

【解决方案2】:

assertSessionHasErrors可以接收数组,as documented

$this->assertSessionHasErrors([
    'field' => 'Field error message.'
]);

【讨论】:

  • 您实际上并不需要将错误放入会话中来测试验证器。您可以从ValidationException 中获取错误,例如$ex->errors()
  • 这里只使用密钥。这不会测试错误消息,只是该字段有消息。
  • 我认为这在某一时刻可能是正确的,但从 6.x 开始,除了字段/键之外,您可以传递值来测试特定的错误消息他们自己。在 Laravel 文档中公关:laravel.com/docs/6.x/http-tests#assert-session-has-errors
【解决方案3】:

我认为还有一种更优雅的方式:

如果您通过类 GeneralException 抛出异常,您可以在单元测试中检查会话是否存在抛出异常的 flash_danger

让我们做一个实际的例子:我们想测试管理员不能激活一个已经激活的目录项。

测试功能

public function an_admin_cannot_activate_an_activated_catalogue()
{
    $catalogue = factory(Catalogue::class)->states('active')->create();
    $response = $this->get("/admin/questionnaire/catalogue/{$catalogue->id}/activate");
    $response->assertSessionHas(['flash_danger' => __('The catalogue item is already activated.')]);
}

模型/复制功能

如果它被激活,我们会抛出一个异常,然后可以通过测试函数进行检查。

public function activate(Catalogue $catalogue) : Catalogue
{
    if ($catalogue->is_active) {
        throw new GeneralException(__('The catalogue item is already activated.'));
    }

    $catalogue->is_active = 1;
    $activated = $catalogue->save();

    if($activated) {
        return $catalogue;
    }
}

【讨论】:

    【解决方案4】:

    您可以使用assertStatusassertJson 的组合

    ...
    ->assertStatus(422)
    ->assertJson([
         'errors' => [
              'field' => [
                   'Error message'  
              ]
          ]
    ]);
    

    【讨论】:

      【解决方案5】:

      你可以使用 $response->assertSessionHasErrors('key')

      https://laravel.com/docs/7.x/http-tests#assert-session-has-errors

      必需属性的示例是

      $response = $this->json('POST', '/api/courses', $this->data([
          'name' => '',
          'api_token' => $this->user->api_token
      ]));
      
      $response->assertSessionHasErrors('name');
      

      你可以添加一个额外的断言,以确保没有条目被添加到数据库中,在这种情况下“断言没有添加课程”

      $this->assertCount(0, Course::all());
      

      对于多个必需的属性,您可以使用类似以下的循环:

      collect(['name', 'description', 'amount'])->each(function ($field) {
          $response = $this->json('POST', '/api/courses', $this->data([
              $field => '',
              'api_token' => $this->user->api_token
          ]));
      
          $response->assertSessionHasErrors($field);
          $this->assertCount(0, Course::all());
      });
      

      【讨论】:

        【解决方案6】:

        实际上,您可以使用dd()session('errors') 轻松抛出验证错误

        由于错误包存储在会话中,您可以在单元测试中添加 dd(session('errors')) 以查看您缺少哪些字段。

        最后你可以通过添加$response->assertSessionHasErrors('field_name');来编写更合适的测试

        【讨论】:

          【解决方案7】:

          首先我使用

          $this->post() 
          

          而不是

          $this->jsonPost()
          

          不知道为什么,由于某种原因,会话不会出来。

          那我就用

          $response->assertSessionHasErrors('field_name', 'Error Message!');
          

          要找出错误消息是什么,您必须转储它

          $response->dumpSession();
          

          【讨论】:

            猜你喜欢
            • 2020-10-28
            • 2018-11-09
            • 1970-01-01
            • 2013-01-21
            • 2018-06-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多