Skip to content

Commit a6af55c

Browse files
authored
refactor tests (#23)
motivation: get test suite in better shape for core API changes changes: * test lambda behavior instead of sevrer error handling in string/codable test suites * add more basic behavior tests to core tesr suite * refacotr common parts to make tests DRYer * remove custom result types (pre swift 5 leftovers)
1 parent df4e247 commit a6af55c

9 files changed

+367
-332
lines changed

Tests/SwiftAwsLambdaTests/Lambda+CodeableTest.swift

Lines changed: 68 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,45 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import NIO
1516
@testable import SwiftAwsLambda
1617
import XCTest
1718

1819
class CodableLambdaTest: XCTestCase {
1920
func testSuccess() {
20-
let server = MockLambdaServer(behavior: GoodBehavior())
21+
let server = MockLambdaServer(behavior: Behavior())
2122
XCTAssertNoThrow(try server.start().wait())
2223
defer { XCTAssertNoThrow(try server.stop().wait()) }
2324

25+
struct Handler: LambdaCodableHandler {
26+
func handle(context: Lambda.Context, payload: Request, callback: @escaping LambdaCodableCallback<Response>) {
27+
callback(.success(Response(requestId: payload.requestId)))
28+
}
29+
}
2430
let maxTimes = Int.random(in: 1 ... 10)
2531
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
26-
let result = Lambda.run(handler: CodableEchoHandler(), configuration: configuration)
27-
assertLambdaLifecycleResult(result: result, shoudHaveRun: maxTimes)
32+
let result = Lambda.run(handler: Handler(), configuration: configuration)
33+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
2834
}
2935

3036
func testFailure() {
31-
let server = MockLambdaServer(behavior: BadBehavior())
37+
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
3238
XCTAssertNoThrow(try server.start().wait())
3339
defer { XCTAssertNoThrow(try server.stop().wait()) }
3440

35-
let result = Lambda.run(handler: CodableEchoHandler())
36-
assertLambdaLifecycleResult(result: result, shouldFailWithError: LambdaRuntimeClientError.badStatusCode(.internalServerError))
41+
struct Handler: LambdaCodableHandler {
42+
func handle(context: Lambda.Context, payload: Request, callback: @escaping LambdaCodableCallback<Response>) {
43+
callback(.failure(TestError("boom")))
44+
}
45+
}
46+
let maxTimes = Int.random(in: 1 ... 10)
47+
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
48+
let result = Lambda.run(handler: Handler(), configuration: configuration)
49+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
3750
}
3851

3952
func testClosureSuccess() {
40-
let server = MockLambdaServer(behavior: GoodBehavior())
53+
let server = MockLambdaServer(behavior: Behavior())
4154
XCTAssertNoThrow(try server.start().wait())
4255
defer { XCTAssertNoThrow(try server.stop().wait()) }
4356

@@ -46,40 +59,34 @@ class CodableLambdaTest: XCTestCase {
4659
let result = Lambda.run(configuration: configuration) { (_, payload: Request, callback) in
4760
callback(.success(Response(requestId: payload.requestId)))
4861
}
49-
assertLambdaLifecycleResult(result: result, shoudHaveRun: maxTimes)
62+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
5063
}
5164

5265
func testClosureFailure() {
53-
let server = MockLambdaServer(behavior: BadBehavior())
66+
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
5467
XCTAssertNoThrow(try server.start().wait())
5568
defer { XCTAssertNoThrow(try server.stop().wait()) }
5669

57-
let result: LambdaLifecycleResult = Lambda.run { (_, payload: Request, callback) in
58-
callback(.success(Response(requestId: payload.requestId)))
59-
}
60-
assertLambdaLifecycleResult(result: result, shouldFailWithError: LambdaRuntimeClientError.badStatusCode(.internalServerError))
61-
}
62-
}
63-
64-
private func assertLambdaLifecycleResult(result: LambdaLifecycleResult, shoudHaveRun: Int = 0, shouldFailWithError: Error? = nil) {
65-
switch result {
66-
case .success(let count):
67-
if shouldFailWithError != nil {
68-
XCTFail("should fail with \(shouldFailWithError!)")
69-
}
70-
XCTAssertEqual(shoudHaveRun, count, "should have run \(shoudHaveRun) times")
71-
case .failure(let error):
72-
if shouldFailWithError == nil {
73-
XCTFail("should succeed, but failed with \(error)")
74-
break
70+
let maxTimes = Int.random(in: 1 ... 10)
71+
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
72+
let result: Result<Int, Error> = Lambda.run(configuration: configuration) { (_, _: Request, callback: (Result<Response, Error>) -> Void) in
73+
callback(.failure(TestError("boom")))
7574
}
76-
XCTAssertEqual(shouldFailWithError?.localizedDescription, error.localizedDescription, "expected error to mactch")
75+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
7776
}
7877
}
7978

8079
// TODO: taking advantage of the fact we know the serialization is json
81-
private struct GoodBehavior: LambdaServerBehavior {
82-
let requestId = UUID().uuidString
80+
private struct Behavior: LambdaServerBehavior {
81+
let requestId: String
82+
let payload: String
83+
let result: Result<String?, TestError>
84+
85+
init(requestId: String = UUID().uuidString, payload: String = "hello", result: Result<String?, TestError> = .success("hello")) {
86+
self.requestId = requestId
87+
self.payload = payload
88+
self.result = result
89+
}
8390

8491
func getWork() -> GetWorkResult {
8592
guard let payload = try? JSONEncoder().encode(Request(requestId: requestId)) else {
@@ -93,48 +100,48 @@ private struct GoodBehavior: LambdaServerBehavior {
93100
return .success((requestId: self.requestId, payload: payloadAsString))
94101
}
95102

96-
func processResponse(requestId: String, response: String) -> ProcessResponseResult {
97-
guard let data = response.data(using: .utf8) else {
98-
XCTFail("decoding error")
99-
return .failure(.internalServerError)
100-
}
101-
guard let response = try? JSONDecoder().decode(Response.self, from: data) else {
102-
XCTFail("decoding error")
103+
func processResponse(requestId: String, response: String?) -> Result<Void, ProcessResponseError> {
104+
switch self.result {
105+
case .success(let expected) where expected != nil:
106+
guard let data = response?.data(using: .utf8) else {
107+
XCTFail("decoding error")
108+
return .failure(.internalServerError)
109+
}
110+
guard let response = try? JSONDecoder().decode(Response.self, from: data) else {
111+
XCTFail("decoding error")
112+
return .failure(.internalServerError)
113+
}
114+
XCTAssertEqual(self.requestId, response.requestId, "expecting requestId to match")
115+
return .success(())
116+
case .success(let expected) where expected == nil:
117+
XCTAssertNil(response)
118+
return .success(())
119+
case .failure:
120+
XCTFail("unexpected to fail, but succeeded with: \(response ?? "undefined")")
103121
return .failure(.internalServerError)
122+
default:
123+
preconditionFailure("invalid state")
104124
}
105-
XCTAssertEqual(self.requestId, response.requestId, "expecting requestId to match")
106-
return .success
107125
}
108126

109-
func processError(requestId: String, error: ErrorResponse) -> ProcessErrorResult {
110-
XCTFail("should not report error")
111-
return .failure(.internalServerError)
127+
func processError(requestId: String, error: ErrorResponse) -> Result<Void, ProcessErrorError> {
128+
XCTAssertEqual(self.requestId, requestId, "expecting requestId to match")
129+
switch self.result {
130+
case .success:
131+
XCTFail("unexpected to succeed, but failed with: \(error)")
132+
return .failure(.internalServerError)
133+
case .failure(let expected):
134+
XCTAssertEqual(expected.description, error.errorMessage, "expecting error to match")
135+
return .success(())
136+
}
112137
}
113138

114-
func processInitError(error: ErrorResponse) -> ProcessInitErrorResult {
139+
func processInitError(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
115140
XCTFail("should not report init error")
116141
return .failure(.internalServerError)
117142
}
118143
}
119144

120-
private struct BadBehavior: LambdaServerBehavior {
121-
func getWork() -> GetWorkResult {
122-
return .failure(.internalServerError)
123-
}
124-
125-
func processResponse(requestId: String, response: String) -> ProcessResponseResult {
126-
return .failure(.internalServerError)
127-
}
128-
129-
func processError(requestId: String, error: ErrorResponse) -> ProcessErrorResult {
130-
return .failure(.internalServerError)
131-
}
132-
133-
func processInitError(error: ErrorResponse) -> ProcessInitErrorResult {
134-
return .failure(.internalServerError)
135-
}
136-
}
137-
138145
private struct Request: Codable {
139146
let requestId: String
140147
init(requestId: String) {
@@ -148,9 +155,3 @@ private struct Response: Codable {
148155
self.requestId = requestId
149156
}
150157
}
151-
152-
private struct CodableEchoHandler: LambdaCodableHandler {
153-
func handle(context: Lambda.Context, payload: Request, callback: @escaping LambdaCodableCallback<Response>) {
154-
callback(.success(Response(requestId: payload.requestId)))
155-
}
156-
}

Tests/SwiftAwsLambdaTests/Lambda+StringTest.swift

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,45 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import NIO
1516
@testable import SwiftAwsLambda
1617
import XCTest
1718

1819
class StringLambdaTest: XCTestCase {
1920
func testSuccess() {
20-
let server = MockLambdaServer(behavior: GoodBehavior())
21+
let server = MockLambdaServer(behavior: Behavior())
2122
XCTAssertNoThrow(try server.start().wait())
2223
defer { XCTAssertNoThrow(try server.stop().wait()) }
2324

25+
struct Handler: LambdaStringHandler {
26+
func handle(context: Lambda.Context, payload: String, callback: @escaping LambdaStringCallback) {
27+
callback(.success(payload))
28+
}
29+
}
2430
let maxTimes = Int.random(in: 1 ... 10)
2531
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
26-
let result = Lambda.run(handler: StringEchoHandler(), configuration: configuration)
27-
assertLambdaLifecycleResult(result: result, shoudHaveRun: maxTimes)
32+
let result = Lambda.run(handler: Handler(), configuration: configuration)
33+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
2834
}
2935

3036
func testFailure() {
31-
let server = MockLambdaServer(behavior: BadBehavior())
37+
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
3238
XCTAssertNoThrow(try server.start().wait())
3339
defer { XCTAssertNoThrow(try server.stop().wait()) }
3440

35-
let result = Lambda.run(handler: StringEchoHandler())
36-
assertLambdaLifecycleResult(result: result, shouldFailWithError: LambdaRuntimeClientError.badStatusCode(.internalServerError))
41+
struct Handler: LambdaStringHandler {
42+
func handle(context: Lambda.Context, payload: String, callback: @escaping LambdaStringCallback) {
43+
callback(.failure(TestError("boom")))
44+
}
45+
}
46+
let maxTimes = Int.random(in: 1 ... 10)
47+
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
48+
let result = Lambda.run(handler: Handler(), configuration: configuration)
49+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
3750
}
3851

3952
func testClosureSuccess() {
40-
let server = MockLambdaServer(behavior: GoodBehavior())
53+
let server = MockLambdaServer(behavior: Behavior())
4154
XCTAssertNoThrow(try server.start().wait())
4255
defer { XCTAssertNoThrow(try server.stop().wait()) }
4356

@@ -46,81 +59,64 @@ class StringLambdaTest: XCTestCase {
4659
let result = Lambda.run(configuration: configuration) { (_, payload: String, callback) in
4760
callback(.success(payload))
4861
}
49-
assertLambdaLifecycleResult(result: result, shoudHaveRun: maxTimes)
62+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
5063
}
5164

5265
func testClosureFailure() {
53-
let server = MockLambdaServer(behavior: BadBehavior())
66+
let server = MockLambdaServer(behavior: Behavior(result: .failure(TestError("boom"))))
5467
XCTAssertNoThrow(try server.start().wait())
5568
defer { XCTAssertNoThrow(try server.stop().wait()) }
5669

57-
let result: LambdaLifecycleResult = Lambda.run { (_, payload: String, callback) in
58-
callback(.success(payload))
70+
let maxTimes = Int.random(in: 1 ... 10)
71+
let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes))
72+
let result: Result<Int, Error> = Lambda.run(configuration: configuration) { (_, _: String, callback) in
73+
callback(.failure(TestError("boom")))
5974
}
60-
assertLambdaLifecycleResult(result: result, shouldFailWithError: LambdaRuntimeClientError.badStatusCode(.internalServerError))
75+
assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes)
6176
}
6277
}
6378

64-
private func assertLambdaLifecycleResult(result: LambdaLifecycleResult, shoudHaveRun: Int = 0, shouldFailWithError: Error? = nil) {
65-
switch result {
66-
case .success(let count):
67-
if shouldFailWithError != nil {
68-
XCTFail("should fail with \(shouldFailWithError!)")
69-
}
70-
XCTAssertEqual(shoudHaveRun, count, "should have run \(shoudHaveRun) times")
71-
case .failure(let error):
72-
if shouldFailWithError == nil {
73-
XCTFail("should succeed, but failed with \(error)")
74-
break
75-
}
76-
XCTAssertEqual(shouldFailWithError?.localizedDescription, error.localizedDescription, "expected error to mactch")
79+
private struct Behavior: LambdaServerBehavior {
80+
let requestId: String
81+
let payload: String
82+
let result: Result<String?, TestError>
83+
84+
init(requestId: String = UUID().uuidString, payload: String = "hello", result: Result<String?, TestError> = .success("hello")) {
85+
self.requestId = requestId
86+
self.payload = payload
87+
self.result = result
7788
}
78-
}
7989

80-
private struct GoodBehavior: LambdaServerBehavior {
81-
let requestId = UUID().uuidString
82-
let payload = "hello"
8390
func getWork() -> GetWorkResult {
8491
return .success((requestId: self.requestId, payload: self.payload))
8592
}
8693

87-
func processResponse(requestId: String, response: String) -> ProcessResponseResult {
94+
func processResponse(requestId: String, response: String?) -> Result<Void, ProcessResponseError> {
8895
XCTAssertEqual(self.requestId, requestId, "expecting requestId to match")
89-
XCTAssertEqual(self.payload, response, "expecting response to match")
90-
return .success
96+
switch self.result {
97+
case .success(let expected):
98+
XCTAssertEqual(expected, response, "expecting response to match")
99+
return .success(())
100+
case .failure:
101+
XCTFail("unexpected to fail, but succeeded with: \(response ?? "undefined")")
102+
return .failure(.internalServerError)
103+
}
91104
}
92105

93-
func processError(requestId: String, error: ErrorResponse) -> ProcessErrorResult {
94-
XCTFail("should not report error")
95-
return .failure(.internalServerError)
106+
func processError(requestId: String, error: ErrorResponse) -> Result<Void, ProcessErrorError> {
107+
XCTAssertEqual(self.requestId, requestId, "expecting requestId to match")
108+
switch self.result {
109+
case .success:
110+
XCTFail("unexpected to succeed, but failed with: \(error)")
111+
return .failure(.internalServerError)
112+
case .failure(let expected):
113+
XCTAssertEqual(expected.description, error.errorMessage, "expecting error to match")
114+
return .success(())
115+
}
96116
}
97117

98-
func processInitError(error: ErrorResponse) -> ProcessInitErrorResult {
118+
func processInitError(error: ErrorResponse) -> Result<Void, ProcessErrorError> {
99119
XCTFail("should not report init error")
100120
return .failure(.internalServerError)
101121
}
102122
}
103-
104-
private struct BadBehavior: LambdaServerBehavior {
105-
func getWork() -> GetWorkResult {
106-
return .failure(.internalServerError)
107-
}
108-
109-
func processResponse(requestId: String, response: String) -> ProcessResponseResult {
110-
return .failure(.internalServerError)
111-
}
112-
113-
func processError(requestId: String, error: ErrorResponse) -> ProcessErrorResult {
114-
return .failure(.internalServerError)
115-
}
116-
117-
func processInitError(error: ErrorResponse) -> ProcessInitErrorResult {
118-
return .failure(.internalServerError)
119-
}
120-
}
121-
122-
private struct StringEchoHandler: LambdaStringHandler {
123-
func handle(context: Lambda.Context, payload: String, callback: @escaping LambdaStringCallback) {
124-
callback(.success(payload))
125-
}
126-
}

0 commit comments

Comments
 (0)