unit testing - Swift Mocking Class -
as far know there no possible solution mocking , stubbing methods in swift used in objc ocmock, mockito, etc.
i'm aware of technique described here. quite useful in cases, had deadlock :)
i had service layer had contracts(calling method params return object callback). one(greatly simplified) example:
class bar { func todata() -> nsdata { return nsdata() } } class foo { class func fromdata(data: nsdata) -> foo { return foo() } } class servermanager { let sharedinstance = servermanager() class func send(request: nsdata, response: (nsdata)->()) { //some networking code unrelated problem response(nsdata()) } } class mobileservice1 { final class func contract1(request: bar, callback: (foo) -> ()) { servermanager.send(request.todata()) { responsedata in callback(foo.fromdata(responsedata)) } } //contract2(...), contract3(...), etc } therefore somewhere in code had following scenario:
func somewhereinthecode(somebool: bool, someobject: bar) { if somebool { mobileservice1.contract1(someobject) { resultfoo in //self.foo = resultfoo } } else { //mobileservice1.contract2(...) } } and question how heck test this? there better(for testing) alternative code structure without touching contracts themselves?
better late never found solution. make dependency injection of mobileservice1(or better of it's interface) , mock easily:
//declaring interface protocol mobileservicecontracts: class { static func contract1(request: bar, callback: (foo) -> ()) } //make implementation conform interface class mobileservice1 : mobileservicecontracts { final class func contract1(request: bar, callback: (foo) -> ()) { servermanager.send(request.todata()) { responsedata in callback(foo.fromdata(responsedata)) } } //contract2(...), contract3(...), etc } //inject service func somewhereinthecode(somebool: bool, someobject: bar, serviceprovider: mobileservicecontracts.type = mobileservice1.self) { if somebool { serviceprovider.contract1(someobject) { resultfoo in //self.foo = resultfoo } } else { //mobileservice1.contract2(...) } } now can change service in tests:
class mockedmobileservice1: mobileservicecontracts { static func contract1(request: bar, callback: (foo) -> ()) { //do whatever mock } } somewhereinthecode(false, someobject: bar(), serviceprovider: mockedmobileservice1.self) and best part default values can still call old way(not braking change):
somewhereinthecode(false, someobject: bar())
Comments
Post a Comment