Chapter 11: Testing got IOError in swift-nio

Hello gays, today I just wrote my first test case for vapor but got puzzled error in it.

Here is my code:

@testable import App
import Vapor
import XCTest
import FluentPostgreSQL

final class UserTests: XCTestCase {
  
  func testUsersCanBeRetrievedFromAPI() throws {
    // 1
    let expectedName = "Alice"
    let expectedUserName = "alice"
    
    // 2
    var config = Config.default()
    var services = Services.default()
    var env = Environment.testing
    try App.configure(&config, &env, &services)
    let app = try Application(config: config, environment: env, services: services)
    try App.boot(app)
    
    // 3
    let conn = try app.newConnection(to: .psql).wait()
    
    // 4
    let user = User(name: expectedName, username: expectedUserName)
    let savedUser = try user.save(on: conn).wait()
    _ = try User(name: "Luke", username: "luke")
      .save(on: conn).wait()
    
    // 5
    let responder = try app.make(Responder.self)
    
    // 6
    let request = HTTPRequest(method: .GET, url: URL(string: "/api/users")!)
    let wrappedRequest = Request(http: request, using: app)
    
    // 7
    let response = try responder.respond(to: wrappedRequest).wait()
    
    // 8
    let data = response.http.body.data
    let users = try JSONDecoder().decode([User].self, from: data!)
    
    // 9
    XCTAssertEqual(users.count, 2)
    XCTAssertEqual(users[0].name, expectedName)
    XCTAssertEqual(users[0].username, expectedUserName)
    XCTAssertEqual(users[0].id, savedUser.id)
    
    // 10
    conn.close()
  }
}

I did create Postgres in docker by:

docker run --name postgres-test -e POSTGRES_DB=vapor-test \
-e POSTGRES_USER=vapor -e POSTGRES_PASSWORD=password \
-p 5433:5432 -d postgres

And my code stop in here:

@inline(__always)
@discardableResult
internal func wrapSyscall<T: FixedWidthInteger>(where function: StaticString = #function, _ body: () throws -> T) throws -> T {
    while true {
        let res = try body()
        if res == -1 {
            let err = errno
            if err == EINTR {
                continue
            }
            assertIsNotBlacklistedErrno(err: err, where: function)
            throw IOError(errnoCode: err, function: function)
        }
        return res
    }
}

The lldb print err is 57 and function is “getpeername(socket:address:addressLength:)”


Xcode Version 11.0 (11A420a)
MacOS Version 10.14.6
Vapor: 3.3.0

That all looks valid. If you do swift test from the command line, what error do you get? Also what does your configure.swift look like for setting up the DB? Looks like a DB connection issue

I try to run swift test and here is the result:

$ swift test
[3/3] Linking TILAppPackageTests
Test Suite 'All tests' started at 2019-09-25 22:00:23.885
Test Suite 'TILAppPackageTests.xctest' started at 2019-09-25 22:00:23.885
Test Suite 'AppTests' started at 2019-09-25 22:00:23.885
Test Case '-[AppTests.AppTests testNothing]' started.
Test Case '-[AppTests.AppTests testNothing]' passed (0.081 seconds).
Test Suite 'AppTests' passed at 2019-09-25 22:00:23.966.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.081 (0.081) seconds
Test Suite 'UserTests' started at 2019-09-25 22:00:23.966
Test Case '-[AppTests.UserTests testUsersCanBeRetrievedFromAPI]' started.
[ INFO ] Migrating 'psql' database (/Users/arco/Projects/vapor/TILApp/.build/checkouts/fluent/Sources/Fluent/Migration/MigrationConfig.swift:69)
[ INFO ] Migrations complete (/Users/arco/Projects/vapor/TILApp/.build/checkouts/fluent/Sources/Fluent/Migration/MigrationConfig.swift:73)
Test Case '-[AppTests.UserTests testUsersCanBeRetrievedFromAPI]' passed (0.126 seconds).
Test Suite 'UserTests' passed at 2019-09-25 22:00:24.092.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.126 (0.126) seconds
Test Suite 'TILAppPackageTests.xctest' passed at 2019-09-25 22:00:24.092.
	 Executed 2 tests, with 0 failures (0 unexpected) in 0.206 (0.207) seconds
Test Suite 'All tests' passed at 2019-09-25 22:00:24.092.
	 Executed 2 tests, with 0 failures (0 unexpected) in 0.206 (0.207) seconds

And my configure.swift:

import FluentPostgreSQL
import Vapor

/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
  // Register providers first
  try services.register(FluentPostgreSQLProvider())

  // Register routes to the router
  let router = EngineRouter.default()
  try routes(router)
  services.register(router, as: Router.self)

  // Register middleware
  var middlewares = MiddlewareConfig() // Create _empty_ middleware config
  // middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
  middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
  services.register(middlewares)

  var databases = DatabasesConfig()
  
  let databaseName: String
  let databasePort: Int
  
  if env == .testing {
    databaseName = "vapor-test"
    databasePort = 5433
  } else {
    databaseName = "vapor"
    databasePort = 5432
  }
  
  let databaseConfig = PostgreSQLDatabaseConfig(
    hostname: "localhost",
    port: databasePort,
    username: "vapor",
    database: databaseName,
    password: "password"
  )

  let database = PostgreSQLDatabase(config: databaseConfig)
  databases.add(database: database, as: .psql)
  services.register(databases)

  // Configure migrations
  var migrations = MigrationConfig()
  migrations.add(model: User.self, database: .psql)
  migrations.add(model: Acronym.self, database: .psql)
  migrations.add(model: Category.self, database: .psql)
  migrations.add(model: AcronymCategoryPivot.self, database: .psql)
  services.register(migrations)
}

So it works from the command line? :thinking:

If you disable all breakpoints in Xcode do you get the same error?

:sweat_smile: After disable all the breakpoints, the test case can be passed now.
Thank you!

1 Like