This project is a fully testable SwiftUI iOS app demonstrating clean architecture and protocol-driven GraphQL integration. It fetches and displays a list of users from the GraphQLZero public GraphQL API.
The focus is on separation of concerns, dependency injection, and unit testability, using Swift Testing (@Test, #expect) introduced in Xcode 15+.
- Xcode: 16.4 (16F6)
- Language: Swift 5.10+
- GraphQL API: https://graphqlzero.almansi.me/api
- No external dependencies (Apollo included but not used for codegen)
- Testing: Swift Testing (native), no XCTest
This demo follows an MVVM + DI architecture:
SwiftUI View ⇅ (binds to) ViewModel ⇅ (depends on) GraphQLServiceProtocol ⇄ (implemented by) URLSessionGraphQLService
Key architectural choices:
- ✅ Protocol-oriented design: All business logic depends on
GraphQLServiceProtocol, not concrete classes - ✅ Decoupled networking: The
URLSessionGraphQLServiceimplements raw GraphQL queries using JSON andCodable— simple, inspectable, and easy to test - ✅ No Apollo codegen: Apollo was evaluated but not integrated to keep the demo lightweight and self-contained. Full codegen was unnecessary for the static schema and simple use case.
- ✅ Unit testable: The ViewModel is tested with mock services, and test files are colocated with source for fast TDD workflows
- ✅ Swift Testing over XCTest: Cleaner syntax, native
asyncsupport, no class boilerplate
- Tests are written using Swift Testing
UserListViewModelTests.swiftverifies:- Initial state
- Successful data loading
- Error handling when the service fails
MockGraphQLServicelives only in the test target- No
@testable importrequired — shared files are explicitly included in both targets
Models/ ← Shared model types (e.g., User)
Services/ ← Protocols and service implementations
ViewModels/ ← Observable ViewModels (testable via DI)
Views/ ← SwiftUI views
GraphQLDemoApp-iOSTests/
└── Mocks/ ← Test-only mock services (e.g., MockGraphQLService)
Some test files (like the view model test) live adjacent to the code they test to support TDD workflows.
- ❌ No Apollo code generation
- ❌ No unnecessary 3rd-party frameworks
This keeps the demo focused on testability, Swift-native tooling, and architectural clarity.
This app consumes the users query from:
https://graphqlzero.almansi.me/api
Example query:
query GetUsers {
users {
data {
id
name
username
email
}
}
}