Spiral 的测试包提供了一种非常方便的方式来测试你的应用程序控制器。你可以使用 Spiral\Testing\Http\FakeHttp
类来向你的控制器发送请求并检查响应。
例如,在下面的例子中,我们可以看到对 HomeController
的测试。我们创建了一个 FakeHttp
实例,并用它向 /
端点发送了一个 GET
请求。然后,我们检查了响应是否为 OK
。
namespace Tests\Feature;
use Spiral\Testing\Http\FakeHttp;
use Tests\TestCase;
final class HomeControllerTest extends TestCase
{
private FakeHttp $http;
protected function setUp(): void
{
parent::setUp();
$this->http = $this->fakeHttp();
}
public function testIndex(): void
{
$response = $this->http->get('/');
$response->assertOk();
}
}
这是一种非常直接的方式来测试你的控制器。
当你使用 FakeHttp
类发送请求时,它会直接发送到你的控制器,就像一个真实的请求一样,通过任何中间件和拦截器。你可以在你的测试中使用任何标准的 HTTP 方法,例如 GET
, POST
, DELETE
, PUT
。
FakeHttp
类不会返回一个真实的响应 Psr\Http\Message\ResponseInterface
对象,而是返回一个 Spiral\Testing\Http\TestResponse
对象。它提供了各种有用的断言,让你检查诸如响应状态、标头和正文之类的内容。这使得你可以轻松地测试你的应用程序如何响应不同的请求,并确保其按预期工作。
FakeHttp
类提供了多种方法,用于向你的应用程序发送不同类型的请求。
get()
方法用于发送 GET
请求。它接受多个参数,如 uri
, query
, headers
和 cookies
。
$http = $this->fakeHttp();
$response = $http->get(
uri: '/users',
query: ['sort' => 'desc'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
);
使用 getJson
方法发送一个带有以下标头的 GET
请求:
Accept: application/json
Content-type: application/json
$http = $this->fakeHttp();
$response = $http->getJson(
uri: '/users',
query: ['sort' => 'desc'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
);
$http = $this->fakeHttp();
$response = $http->post(
uri: '/user/1',
data: ['foo' => 'bar'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
files: ['avatar' => ...],
);
注意
data
参数接受一个数组或Psr\Http\Message\StreamInterface
对象。
使用 postJson
方法发送一个带有以下标头的 POST
请求:
Accept: application/json
Content-type: application/json
$http = $this->fakeHttp();
$response = $http->postJson(
uri: '/user/1',
data: ['foo' => 'bar'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
files: ['avatar' => ...],
);
$http = $this->fakeHttp();
$response = $http->put(
uri: '/users',
data: ['foo' => 'bar'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
files: ['avatar' => ...],
);
注意
data
参数接受一个数组或Psr\Http\Message\StreamInterface
对象。
使用 putJson
方法发送一个带有以下标头的 PUT
请求:
Accept: application/json
Content-type: application/json
$http = $this->fakeHttp();
$response = $http->putJson(
uri: '/users',
data: ['foo' => 'bar'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
files: ['avatar' => ...],
);
$http = $this->fakeHttp();
$response = $http->delete(
uri: '/user/1',
data: ['foo' => 'bar'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
files: ['avatar' => ...],
);
注意
data
参数接受一个数组或Psr\Http\Message\StreamInterface
对象。
使用 deleteJson
方法发送一个带有以下标头的 DELETE
请求:
Accept: application/json
Content-type: application/json
$http = $this->fakeHttp();
$response = $http->deleteJson(
uri: '/user/1',
data: ['foo' => 'bar'],
headers: ['Content-type' => 'application/json'],
cookies: ['token' => 'xxx-xxxx'],
files: ['avatar' => ...],
);
是的,你可以使用 withHeaders()
和 withHeader()
方法来为请求添加/设置默认自定义标头。
$http = $this->fakeHttp();
$http->withHeaders(['Content-type' => 'application/json']);
$http->get('/users');
$http = $this->fakeHttp();
$http->withHeader('Content-type', 'application/json');
$http->get('/users');
$http = $this->fakeHttp();
$http->withAuthorizationToken(
token: 'xxx-xxxx',
type: 'Bearer' // 默认值是 'Bearer'
);
此方法将刷新所有默认标头。
$http = $this->fakeHttp();
$http->flushHeaders();
是的,你可以使用 withCookies()
和 withCookie()
方法为请求添加/设置默认自定义 Cookie。
$http = $this->fakeHttp();
$http->withCookies(['theme' => 'dark']);
$http->get('/users');
$http = $this->fakeHttp();
$http->withHeader('theme', 'dark');
$http->get('/users');
此方法将刷新所有默认 Cookie。
$http = $this->fakeHttp();
$http->flushCookies();
Spiral 提供了一些很棒的工具来帮助你在测试 HTTP 请求时与会话进行交互。其中一个工具是 withSession()
方法。它允许你在向你的应用程序发送请求之前,将会话数据设置为特定的数组。当你需要为你的测试加载包含某些特定数据的会话时,这会非常方便。
例如,你可以像这样设置会话数据:
$http = $this->fakeHttp();
$http->withSession(
data: ['fav_color' => 'blue'],
lifetime: 3600, // 默认值是 3600
id: null // 默认值是 null
)->get('/users');
会话通常用于维护当前已通过身份验证的用户的状态。这就是为什么 Spiral 提供了一个 withActor
方法,它使得在测试期间将给定的用户身份验证为当前用户变得容易。
此方法允许你通过将用户对象的一个实例传递给该方法,快速而轻松地为测试设置经过身份验证的用户。
$http = $this->fakeHttp();
$user = new User();
$http->withActor($user)->get('/profile');
当你调用 withActor()
方法时,一个 Spiral\Testing\Auth\FakeActorProvider
对象被绑定到容器,实现了 Spiral\Auth\ActorProviderInterface
,并且这个对象将在每次调用 getActor()
方法时返回你传递的用户。这允许应用程序在测试期间访问已通过身份验证的用户,就像在正常操作期间一样。
在向你的应用程序发送请求之后,你可以使用便捷的方法来测试响应。
断言响应具有给定的标头。
// 断言响应具有名为 Content-Type 的标头。
$response->assertHasHeader(name: 'Content-type');
// 断言响应具有名为 Content-Type 且值是给定值的标头。
$response->assertHasHeader(name: 'Content-type', value: 'application/json');
断言响应没有给定的标头。
$response->assertHeaderMissing(name: 'Content-type');
断言响应具有给定的状态码。
$response->assertStatus(status: 200);
断言响应具有 200 状态码。
$response->assertOk();
断言响应具有 201 状态码。
$response->assertCreated();
断言响应具有 202 状态码。
$response->assertAccepted();
断言响应具有 204 状态码并且主体为空。
$response->assertNoContent(
status: 204 // 默认值是 204
);
断言响应具有 404 状态码。
$response->assertNotFound();
断言响应具有 403 状态码。
$response->assertForbidden();
断言响应具有 401 状态码。
$response->assertUnauthorized();
断言响应具有 422 状态码。
$response->assertUnauthorized();
断言响应主体等于给定的值。
$response->assertBodySame(needle: "<html>...</html>");
断言响应主体不等于给定的值。
$response->assertBodyNotSame(needle: "<html>...</html>");
断言响应主体包含给定的字符串。
$response->assertBodyContains(needle: "<div>...</div>");
断言响应具有给定的 Cookie。
$response->assertCookieExists(key: 'theme');
断言响应具有给定的 Cookie,且该 Cookie 具有给定的值。
$response->assertCookieSame(key: 'theme', value: 'dark');
断言响应没有给定的 Cookie。
$response->assertCookieMissed(key: 'theme');
是的,FakeHttp
类提供了 getFileFactory
方法,该方法可用于为测试目的生成虚拟文件或图像。此方法返回 Spiral\Testing\Http\FileFactory
的一个实例,该实例具有创建不同类型文件的几种方法。
此功能使你可以轻松测试你的应用程序如何处理文件上传,并确保其功能正常。
namespace Tests\Feature;
use Spiral\Testing\Http\FakeHttp;
use Tests\TestCase;
final class UserControllerTest extends TestCase
{
private FakeHttp $http;
protected function setUp(): void
{
parent::setUp();
$this->http = $this->fakeHttp();
}
public function testUploadAvatar(): void
{
// Create a fake image 640x480
$image = $http->getFileFactory()->createImage('avatar.jpg', 640, 480);
$response = $http->post(uri: '/user/1', files: ['avatar' => $image]);
$response->assertOk();
}
}
$image = $http->getFileFactory()->createImage(
filename: 'avatar.jpg',
width: 640,
height: 480
);
$file = $http->getFileFactory()->createFile(
filename: 'foo.txt'
);
你可以设置文件大小(以千字节为单位):
// 创建一个大小为 100kb 的文件
$file = $http->getFileFactory()->createFile(
filename: 'foo.txt',
kilobytes: 100
);
你可以设置 MIME 类型:
// 创建一个大小为 100kb 的文件
$file = $http->getFileFactory()->createFile(
filename: 'foo.txt',
mimeType: 'text/plain'
);
你可以设置一个带有特定内容的文件:
$file = $http->getFileFactory()->createFileWithContent(
filename: 'foo.txt',
content: 'Hello world',
mimeType: 'text/plain'
);