【问题标题】:Testing Controller with PHPUnit, but it throws a 401 Error使用 PHPUnit 测试控制器,但它会引发 401 错误
【发布时间】:2019-05-09 08:05:22
【问题描述】:

我正在用 PHPUnit 做一些测试,但我遇到了一些问题,尤其是在测试控制器时。

我想通过调用路由来测试控制器的路由并检查响应是否为 HTTP-Status 200。但控制台总是出现 smae 错误。

它说明了丢失的令牌。我不知道这是什么令牌。

这也是他得到的 401 错误。

我的 PHPUnit-Test 看起来像这样:

命名空间 App\Tests\Controller;

使用 Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

类 PersonControllerTest 扩展了 WebTestCase { 私人 $client;

protected function setUp()
{
    $this->client = static::createClient([], [
        'PHP_AUTH_USER' => 'user',
        'PHP_AUTH_PW'   => 'pass',
    ]);
}


public function testCreate()
{

    $this->client->request('GET','/create');

    $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
}

public function testIndex()
{

    $this->client->request('GET','/');

    $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
}

}

我用setUp方法中的认证试过了->没用。

你有什么线索吗?

感谢所有答案或/和评论

【问题讨论】:

  • 很难在没有看到很多代码的情况下提出解决方案,但请尝试在 request 方法中添加令牌作为第四个参数,例如 $this->client->request ........, ['HTTP_AUTHORIZATION' => 'Bearer Token'])。此外,如果客户端需要 HTTPS,那么您应该添加 'HTTPS' => true。您使用的是基本身份验证吗?如果是这样,只需删除 PHP_AUTH_USER 和另一个然后使用 Basic your_base_64_token_goes_here 而不是上面的 Bearer。
  • 通常你根本不会测试控制器,至少不会作为单元测试的一部分。控制器应该不包含任何业务逻辑,而只是作为应用程序的入口点,因此所有业务逻辑都应该在单独的类中,控制器在调用时会简单地启动。如果您的控制器中确实有业务逻辑,那么您的代码将展示一个名为 Fat Controller 的反模式。
  • @GordonM 他/她没有对他的控制器进行单元测试。他/她正在做的是 functional testing 完全有效的控制器 - 至少就 Symfony 而言。

标签: php symfony authentication phpunit http-status-code-401


【解决方案1】:

基本认证:

   /**
     * @dataProvider urlProvider
     */
    public function testPageIsSuccessful($url)
    {
        $client = self::createClient([], [
            'PHP_AUTH_USER' => getenv('PHP_AUTH_USER'),
            'PHP_AUTH_PW' => getenv('PHP_AUTH_PW')
        ]);
        $client->request('GET', $url);
        $this->assertTrue($client->getResponse()->isSuccessful());
    }

API 密钥

    /**
     * @dataProvider urlApiProvider
     */
    public function testAPIWorks($url)
    {
        $accessToken = $this->getAccessToken();
        $tokenQuery = http_build_query(['access_token' => $accessToken]);
        $url .= '?' . $tokenQuery;
        $client = self::createClient([]);
        $client->request('GET', $url, [], [], ['HTTP_ACCEPT' => 'application/json']);

        $this->assertTrue($client->getResponse()->isSuccessful());
    }

【讨论】:

    【解决方案2】:
    protected function setUp()
    {
        $this->client = static::createClient();
    
        $this->logIn();
    }
    
    private function logIn()
    {
        $session = $this->client->getContainer()->get('session');
    
        $firewallName = 'test';
        // if you don't define multiple connected firewalls, the context defaults to the firewall name
        // See https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
        $firewallContext = 'test';
    
        // you may need to use a different token class depending on your application.
        // for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
        $testUser = new WebserviceUser('Test@Test.com', ['ROLE_ADMIN'],
            array("employeeid" => array(420),
            "mail" => array("testing@test.com")), false);
        $token = new UsernamePasswordToken($testUser, null, $firewallName, ['ROLE_ADMIN']);
        //var_dump($token);
        $session->set('_security_' . $firewallContext, serialize($token));
        $session->save();
    
        $cookie = new Cookie($session->getName(), $session->getId());
        $this->client->getCookieJar()->set($cookie);
    }
    
    
    public function testCreate()
    {
    
        $crawler = $this->client->request('GET', '/create');
        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
    
        $form = $crawler->filter('form')->form([
            'person[name]' => 'Chruit',
            'person[birthdate][month]' => 2,
            'person[birthdate][day]' => 15,
            'person[birthdate][year]' => 2014,
        ]);
    
        $this->client->submit($form);
    }
    
    public function testIndex()
    {
    
        $this->client->request('GET', '/');
    
        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
    }
    

    }

    解决方案就是登录函数。 $testUser 需要在您的 Active Directory 或您的网络中。其余参数无关紧要。

    我的防火墙阻止了它,所以我无法以正常方式进行操作。

    如果您这样做,您必须在安装 PHPUnit 时创建的 secourity.yaml 中添加一些内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 2015-03-24
      • 1970-01-01
      • 2022-01-17
      • 2021-08-16
      • 2010-12-28
      相关资源
      最近更新 更多