Testing¶
Vapor includes a module named XCTVapor
that provides test helpers built on XCTest
. These testing helpers allow you to send test requests to your Vapor application programmatically or running over an HTTP server.
Getting Started¶
To use the XCTVapor
module, ensure it has been added to your package's test target.
let package = Package(
...
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0")
],
targets: [
...
.testTarget(name: "AppTests", dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
])
]
)
Then, add import XCTVapor
at the top of your test files. Create classes extending XCTestCase
to write test cases.
import XCTVapor
final class MyTests: XCTestCase {
func testStub() throws {
// Test here.
}
}
Each function beginning with test
will run automatically when your app is tested.
Running Tests¶
Use cmd+u
with the -Package
scheme selected to run tests in Xcode. Use swift test --enable-test-discovery
to test via the CLI.
Testable Application¶
Initialize an instance of Application
using the .testing
environment. You must call app.shutdown()
before this application deinitializes.
The shutdown is necessary to help release the resources that the app has claimed. In particular it is important to release the threads the application requests at startup. If you do not call shutdown()
on the app after each unit test, you may find your test suite crash with a precondition failure when allocating threads for a new instance of Application
.
let app = Application(.testing)
defer { app.shutdown() }
try configure(app)
Pass the Application
to your package's configure(_:)
method to apply your configuration. Any test-only configurations can be applied after.
Send Request¶
To send a test request to your application, use the test
method.
try app.test(.GET, "hello") { res in
XCTAssertEqual(res.status, .ok)
XCTAssertEqual(res.body.string, "Hello, world!")
}
The first two parameters are the HTTP method and URL to request. The trailing closure accepts the HTTP response which you can verify using XCTAssert
methods.
For more complex requests, you can supply a beforeRequest
closure to modify headers or encode content. Vapor's Content API is available on both the test request and response.
try app.test(.POST, "todos", beforeRequest: { req in
try req.content.encode(["title": "Test"])
}, afterResponse: { res in
XCTAssertEqual(res.status, .created)
let todo = try res.content.decode(Todo.self)
XCTAssertEqual(todo.title, "Test")
})
Testable Method¶
Vapor's testing API supports sending test requests programmatically and via a live HTTP server. You can specify which method you would like to use by using the testable
method.
// Use programmatic testing.
app.testable(method: .inMemory).test(...)
// Run tests through a live HTTP server.
app.testable(method: .running).test(...)
The inMemory
option is used by default.
The running
option supports passing a specific port to use. By default 8080
is used.
.running(port: 8123)