Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions Sources/HTTPMock/Internal/HTTPMockLog.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,54 @@ public enum HTTPMockLog {
public static var level: Level = .trace

public static func error(_ message: @autoclosure () -> String) {
if should(.error) {
let level = Level.error
if shouldLog(level) {
let message = message()
logger.error("[HTTPMock][\(level.description)] \(message, privacy: .public)")
printToConsole("⛔️ \(message)", level: .error)
printToConsole("⛔️ \(message)", level: level)
}
}

public static func warning(_ message: @autoclosure () -> String) {
if should(.warning) {
let level = Level.warning
if shouldLog(level) {
let message = message()
logger.warning("[HTTPMock][\(level.description)] \(message, privacy: .public)")
printToConsole("⚠️ \(message)", level: .warning)
printToConsole("⚠️ \(message)", level: level)
}
}

public static func info(_ message: @autoclosure () -> String) {
if should(.info) {
let level = Level.info
if shouldLog(level) {
let message = message()
logger.info("[HTTPMock][\(level.description)] \(message, privacy: .public)")
printToConsole(message, level: .info)
printToConsole(message, level: level)
}
}

public static func debug(_ message: @autoclosure () -> String) {
if should(.debug) {
let level = Level.debug
if shouldLog(level) {
let message = message()
logger.debug("[HTTPMock][\(level.description)] \(message, privacy: .public)")
printToConsole(message, level: .debug)
printToConsole(message, level: level)
}
}

public static func trace(_ message: @autoclosure () -> String) {
if should(.trace) {
let level = Level.trace
if shouldLog(level) {
let message = message()
logger.log("[HTTPMock][\(level.description)] \(message, privacy: .public)")
printToConsole(message, level: .trace)
printToConsole(message, level: level)
}
}

// MARK: - Private methods

@inline(__always)
private static func should(_ l: Level) -> Bool {
private static func shouldLog(_ l: Level) -> Bool {
isEnabled && l.rawValue <= level.rawValue
}

Expand Down
5 changes: 5 additions & 0 deletions Sources/HTTPMock/Internal/HTTPMockURLProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ final class HTTPMockURLProtocol: URLProtocol {
}
task.resume()

case .throwError(let errorToThrow):
HTTPMockLog.info("No mock found for incoming request '\(requestDescription)' — throwing provided error")

client?.urlProtocol(self, didFailWithError: errorToThrow as NSError)

case .fatalError:
HTTPMockLog.info("No mock found for incoming request '\(requestDescription)' — performing a fatalError")

Expand Down
5 changes: 4 additions & 1 deletion Sources/HTTPMock/Models/UnmockedPolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ public enum UnmockedPolicy {
/// Let the request pass through to the internet.
/// Useful for integration tests where you want to mock some responses, but let others hit actual network.
case passthrough


/// Throw the specified error when an unmocked request is encountered.
case throwError(Error)

/// Perform a `fatalError()` call to abruptly end the running app/test.
/// Useful for strict testing of your networking.
case fatalError
Expand Down
21 changes: 21 additions & 0 deletions Tests/HTTPMockTests/HTTPMockTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,20 @@ struct HTTPMockTests {
#expect(data3.toString == "Different mock")
}

@Test
func unmockedPolicy_throwError() async throws {
let url = try #require(URL(string: "https://example.com/throw-error"))

httpMock.unmockedPolicy = .throwError(UnmockedError.wasThrown)

do {
_ = try await httpMock.urlSession.data(from: url)
Issue.record("Expected error not thrown")
} catch {
#expect((error as NSError).domain == UnmockedError.errorDomain)
}
}

@Test
func itDoesNotRegisterTheKeyIfNoResponsesAreProvided() {
let key = makeKey()
Expand Down Expand Up @@ -664,3 +678,10 @@ struct HTTPMockTests {
)
}
}

private enum UnmockedError: Int, Error, CustomNSError {
case wasThrown = 666

static var errorDomain: String { "HTTPMock.UnmockedError" }
var errorCode: Int { rawValue }
}