由于从电子邮件中提取的令牌损坏,功能测试失败
Functional test fails due to corrupted token extracted from email
在 Symfony 5 项目中,当从电子邮件中提取的确认令牌损坏时,用户注册的功能测试失败。 (电子邮件是用 SwiftMailer 完成的,因为它能够发送日志。)
测试从填写包含用户名和电子邮件地址的表格开始。在保存时发送电子邮件。因为测试包括 $this->client->followRedirects(false);
,所以测试可以访问电子邮件的内容。当从电子邮件中提取令牌时,它包含额外的字符。因此,当测试尝试 $this->client->request('GET', '/register/reset/' . $token);
时,由于注册数据无效,测试失败。
这是一个测试版本:
public function testReplacementEmail() {
$this->client->clickLink('Staff');
$this->client->clickLink('Replace');
$this->client->followRedirects(false);
$this->client->submitForm('Save', [
'user[fname]' => 'Useless',
'user[sname]' => 'Garbage',
'user[email]' => 'ugar@bogus.info'
]);
$mailCollector = $this->client->getProfile()->getCollector('swiftmailer');
$this->assertSame(1, $mailCollector->getMessageCount());
$collectedMessages = $mailCollector->getMessages();
$message = $collectedMessages[0];
$this->assertStringContainsString('has been asked to designate', $message);
$string = 'register/reset/';
$offset = strlen($string);
$pos = strpos($message, $string) + $offset;
$token = substr($message, $pos, 32);
var_dump($token);
$this->client->followRedirects(true);
$this->client->request('GET', '/logout');
$this->client->request('GET', '/register/reset/' . $token);
$this->client->submitForm('Save', [
'new_password[plainPassword][first]' => '123Abc',
'new_password[plainPassword][second]' => '123Abc',
]);
$this->assertStringContainsString('You are now the registered representative', $this->client->getResponse()->getContent());
}
我已经在处理 Replace
link 行 $token = md5(uniqid(rand(), true));var_dump($token);
的控制器中包含了为了获得一个纯粹的令牌。当测试为 运行 时,这些行会产生如下内容:
string(32) "ad47260162194f9ab6deb55eb4f38178"
如果我在测试中使用 var_dump($message);
访问电子邮件的内容,我会看到类似这样的内容:
href="http://localhost/register/reset/ad47260162194f9ab6deb55eb4f38178"
然而,在测试包括 var_dump($token);
的地方,我看到的却是这样的:
string(32) "7260162194f9ab6d=
eb55eb4f38178"
=\r\n
的存在(在 Windows 系统上)导致 link 失败。
我想知道为什么会出现这些额外的字符,以及如何尽可能避免它们。
您的字符串中存在 =\r\n
表明该消息是 MIME-encoded 和 quoted printable 并且您的 link 跨越了一行结尾。 SwiftMailer 消息对象似乎有一个神奇的 __toString()
方法(奇怪的是,IMO)产生消息的 encoded 形式。如果你想要原始的原始消息字符串,你可以调用消息对象的 getBody()
方法,然后只使用你的 strpos()
测试结果。
在 Symfony 5 项目中,当从电子邮件中提取的确认令牌损坏时,用户注册的功能测试失败。 (电子邮件是用 SwiftMailer 完成的,因为它能够发送日志。)
测试从填写包含用户名和电子邮件地址的表格开始。在保存时发送电子邮件。因为测试包括 $this->client->followRedirects(false);
,所以测试可以访问电子邮件的内容。当从电子邮件中提取令牌时,它包含额外的字符。因此,当测试尝试 $this->client->request('GET', '/register/reset/' . $token);
时,由于注册数据无效,测试失败。
这是一个测试版本:
public function testReplacementEmail() {
$this->client->clickLink('Staff');
$this->client->clickLink('Replace');
$this->client->followRedirects(false);
$this->client->submitForm('Save', [
'user[fname]' => 'Useless',
'user[sname]' => 'Garbage',
'user[email]' => 'ugar@bogus.info'
]);
$mailCollector = $this->client->getProfile()->getCollector('swiftmailer');
$this->assertSame(1, $mailCollector->getMessageCount());
$collectedMessages = $mailCollector->getMessages();
$message = $collectedMessages[0];
$this->assertStringContainsString('has been asked to designate', $message);
$string = 'register/reset/';
$offset = strlen($string);
$pos = strpos($message, $string) + $offset;
$token = substr($message, $pos, 32);
var_dump($token);
$this->client->followRedirects(true);
$this->client->request('GET', '/logout');
$this->client->request('GET', '/register/reset/' . $token);
$this->client->submitForm('Save', [
'new_password[plainPassword][first]' => '123Abc',
'new_password[plainPassword][second]' => '123Abc',
]);
$this->assertStringContainsString('You are now the registered representative', $this->client->getResponse()->getContent());
}
我已经在处理 Replace
link 行 $token = md5(uniqid(rand(), true));var_dump($token);
的控制器中包含了为了获得一个纯粹的令牌。当测试为 运行 时,这些行会产生如下内容:
string(32) "ad47260162194f9ab6deb55eb4f38178"
如果我在测试中使用 var_dump($message);
访问电子邮件的内容,我会看到类似这样的内容:
href="http://localhost/register/reset/ad47260162194f9ab6deb55eb4f38178"
然而,在测试包括 var_dump($token);
的地方,我看到的却是这样的:
string(32) "7260162194f9ab6d=
eb55eb4f38178"
=\r\n
的存在(在 Windows 系统上)导致 link 失败。
我想知道为什么会出现这些额外的字符,以及如何尽可能避免它们。
您的字符串中存在 =\r\n
表明该消息是 MIME-encoded 和 quoted printable 并且您的 link 跨越了一行结尾。 SwiftMailer 消息对象似乎有一个神奇的 __toString()
方法(奇怪的是,IMO)产生消息的 encoded 形式。如果你想要原始的原始消息字符串,你可以调用消息对象的 getBody()
方法,然后只使用你的 strpos()
测试结果。