Turning Singleton Usage into Testable Code

Turning Singleton Usage into Testable Code

See how you can wrap any singleton behind a protocol to make it injectable and your code fully testable 💯 The blog post shows how to deal with URLSession.shared usage. The same strategy can be applied to all other singletons in your code! The problem Service uses URLSession.shared directly. Tight coupling makes unit testing impossible without real network calls. struct PostsAPISerivce { func fetchPosts() async throws -> [Post] { let url = URL(string: ".../posts")! let (data, _) = try await URLSession.shared.data(from: url) return try JSONDecoder().decode([Post].self, from: data) } } In the sections, you’ll get step-by-step guide of making this service testable. These same steps can be applied to all other singletons found in your code. ...

May 27, 2025 · 2 min · Maciej Gomolka
Concurrency-Safe Testing in Swift 6.1 with @TaskLocal and Test Scoping

Concurrency-Safe Testing in Swift 6.1 with @TaskLocal and Test Scoping

Today’s example shows a static property providing the current date. Perfect mechanism when we don’t want to inject it everywhere where it’s used. How to test it? Check it out ⤵️ Initial setup let currentDateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short formatter.timeStyle = .none return formatter }() var currentDateFormatted: String { currentDateFormatter.string(from: DateEnvironment.currentDate()) } enum DateEnvironment { static var currentDate: () -> Date = Date.init } extension Date { // 16.04.2025 static let sixteenthOfApril = Date(timeIntervalSince1970: 1744840515) } Old way - XCTest Override the static property in tests. Works, but not concurrency-safe (Ok, for XCTest because test ran serially). class CurrentDateFormatterTests: XCTestCase { func test_dateFormatting() { // ✅ DateEnvironment.currentDate = { .sixteenthOfApril } XCTAssertEqual(currentDateFormatted, "16.04.2025") } } Swift Testing before Swift 6.1 enum DateEnvironment { @TaskLocal static var currentDate: () -> Date = Date.init } struct CurrentDateFormatterTests { @Test func dateFormatting() { // ✅ DateEnvironment.$currentDate .withValue({ .sixteenthOfApril }) { #expect(currentDateFormatted == "16.04.2025") } } } Why @TaskLocal? ...

May 7, 2025 · 2 min · Maciej Gomolka
3 Ways to Name Parameters in Swift Parametrised Tests

3 Ways to Name Parameters in Swift Parametrised Tests

Mind your argument names in Swift Testing’s parametrised tests! As a follow up to my recent post on refactoring to use Swift Testing’s parametrised tests, I’m diving into the crucial - yet often overlooked topic of how to name your parametrised test inputs. Option 1: First Named Tuples Only the first tuple is named, all others rely on positional matching to (a, b, result). ✅ Minimal boilerplate for small input sets ❌ Readability drops after adding more cases ❌ Easy to mix up arguments position ❌ Hard to scan or extend func add(_ a: Int, _ b: Int) -> Int { a + b } ... @Test(arguments: [ (a: 1, b: 2, result: 3), (10, 15, 25), (1, -5, -4), (-1, -5, -6), (0, 0, 0), (1000, 1000, 2000), (10000, 50000, 60000), (-10, -3, -13) ]) func add_returnsCorrectSum(a: Int, b: Int, result: Int) { #expect(add(a, b) == result) } Option 2: Named Tuples Every tuple entry explicitly names all its fields (a: …, b: …, result: …) for all cases. ...

April 24, 2025 · 3 min · Maciej Gomolka
Swift Testing Challange - Can you refactor this?

Swift Testing Challange - Can you refactor this?

Intro Have you already started using Swift Testing instead of XCTest? I’m curious to see how you can refactor the test function (add_returnsCorrectSum) from the code snippet to use all powers of the Swift Testing framework. Could you explain what benefits does your refactored version has compared to my original code snippet? My approach In both approaches the test gives the same result. The point is the refactored version uses a Swift Testing parametrised test, and this makes a real difference. ...

April 17, 2025 · 2 min · Maciej Gomolka
#7 XCTest vs Swift Testing: A modern way of linking bugs

#7 XCTest vs Swift Testing: A modern way of linking bugs

What’s the difference? In XCTest we relied on the old fashioned simple comments to add more context to our test case e.g link to the bug description. With Swift Testing, we now have a special bug trait that can be passed to the @Test macro. The bug trait takes a URL String as argument and optionally a title for the bug allowing us to add short description of it. The key advantage over regular comment is that the bug title is visible in the test results. Better yet, tapping on it takes you directly to the related webpage with the bug report. ...

December 13, 2024 · 2 min · Maciej Gomolka