Hello, Swift Community!
I’m excited to share with you a library that I've been working on called Mockable.
Mockable is a macro driven testing framework that provides automatic mock implementations for your protocols. It offers an intuitive declarative syntax that simplifies the process of mocking services in unit tests. The generated mock implementations can be excluded from release builds using compile conditions.
Example Usage
Given a protocol annotated with the @Mockable
macro:
import Mockable
@Mockable
protocol ProductService {
var url: URL? { get set }
func fetch(for id: UUID) async throws -> Product
func checkout(with product: Product) throws
}
A mock implementation named MockProductService
will be generated, that can be used in unit tests like:
import MockableTest
lazy var productService = MockProductService()
lazy var cartService = CartServiceImpl(productService: productService)
func testCartService() async throws {
let mockURL = URL(string: "apple.com")
let mockError: ProductError = .notFound
let mockProduct = Product(name: "iPhone 15 Pro")
given(productService)
.fetch(for: .any).willReturn(mockProduct)
.checkout(with: .any).willThrow(mockError)
try await cartService.checkout(with: mockProduct, using: mockURL)
verify(productService)
.fetch(for: .value(mockProduct.id)).called(.atLeastOnce)
.checkout(with: .value(mockProduct)).called(.once)
.url(newValue: .value(mockURL)).setCalled(.once)
}
The current feature set includes:
- Support for properties, generic requirements and associated types
- A custom Matcher for parameter checking to support non-equatable types
- Relaxed Mode in which you can implicitly mock members without registration
- Support for async verification with a custom timeout via
calledEventually
Let me know if you have any ideas or questions regarding the package!