A pattern is presented for separating SwiftUI navigation decisions from views so they can be unit tested. Routes are modeled as Hashable enums (Route, StudentRoute, FacultyRoute), and an @Observable Router manages the navigation path bound to a NavigationStack. Business-rule-driven navigation (e.g., student status determining destination after registration) is moved into the router's onRegister method, which can then be tested with Swift Testing, including parameterized tests for multiple student statuses. As applications grow, feature-specific navigation logic can be extracted into coordinators (e.g., RegistrationCoordinator) to keep the router focused on managing the navigation path while coordinators handle destination decisions, making both independently testable.

11m read timeFrom azamsharp.com
Post cover image

Questions this post answers

How do I unit test navigation logic in SwiftUI without writing UI tests?

Separate navigation decisions from views by modeling destinations as a Hashable Route enum and moving decision logic into an @Observable Router class. Business rules, like sending an in-state student to courses and an international student to an agreement screen, live in a method such as onRegister(_:) on the router, so tests can call it directly and assert on router.routes using Swift Testing's #expect, with no view rendering required. daily.dev surfaces patterns like this for developers building testable SwiftUI navigation architectures.

How can I test multiple similar navigation cases in Swift Testing without duplicating test code?

Use Swift Testing's @Test(arguments:) to run a parameterized test once per input value. For example, a single test function can accept StudentStatus.outOfState and StudentStatus.international as arguments, verifying both drive the router to the same agreement route, instead of writing two nearly identical test functions. developers refining Swift Testing workflows can find similar parameterized testing techniques on daily.dev.

366 Impressions