Reputation: 1298
I am finding it difficult to stub methods in structs in swift. I can do it currently using a way that I'll explain below, but it feels wrong to me and would like an opinion on it.
I do not use any third party libraries for stubbing, instead I prefer to override the specific method whose result I need to change. Prior to swift, I would always use classes - so it was easy to subclass and override the method that I needed mocked in my unit test case.
Now most of my constructs are structs as they do not really need to be reference types. But then I cannot override any method in my test cases. I do it currently using protocol extensions as outlined below -
protocol AProtocol {
func a()
func b() // This calls a()
}
extension AProtocol {
func a(){
//Default implementation of a()
}
func b(){
//Default implementation of b() which also calls a()
}
}
struct A:AProtocol {
// Empty. struct A will be used by other classes/structs in the code
}
In my test case
struct TestA:AProtocol {
func a() {
Some mock implementation of a() so that b() can be tested
}
}
So my question is this - There is no real need for struct A to be implemented via a protocol. None of the other classes or structs will ever implement AProtocol. But this is the only way I can mock its methods for unit testing. I think the WWDC session on protocol extensions also showed this way of unit testing, but basically I do not need my struct as an implementation of a protocol.
Is there any other way to stub struct methods in swift (without using any third party libs)? Or a better way to test a struct's methods.
Upvotes: 0
Views: 1033
Reputation: 6504
I'm going to be the person that doesn't answer the question and explores whether you really need to do what you ask I'm afraid.
My question is whether you really need mock the struct. For non mutating functions set up the struct and test the return value. For mutating functions check the state afterwards is as you expect.
With structs there shouldn't generally be side effects beyond the modification so there is no need to track exactly what other functions are called.
The bit that may be close enough to an answer to be slightly helpful:
If you really are doing something with side effects outside the struct I would suggest that you make the object that the effects are being done to or on injectable so that with an additional testing only init you can inject an alternate mock object to receive the side effect calls.
Upvotes: 1