据我所知,swift 中的模拟和 stub 方法没有可能的解决方案,就像我们在 objc 中使用 OCMock、Mockito 等一样。
我知道描述的技术 here .它在某些情况下非常有用,但现在我陷入了僵局:)
我有一个服务层,其中有类似契约(Contract)的东西(使用此参数调用此方法将返回该对象作为回调)。这是一个(大大简化的)示例:
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 to the 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
}
因此在代码的某处我有以下场景:
func someWhereInTheCode(someBool: Bool, someObject: Bar)
{
if someBool
{
MobileService1.Contract1(someObject) { resultFoo in
//self.Foo = resultFoo
}
}
else
{
//MobileService1.Contract2(...)
}
}
现在的问题是我到底该如何测试它?在不触及合约本身的情况下,是否有更好的(用于测试)代码结构替代方案?
最佳答案
迟到总比不到好,我找到了解决方案。只需对 MobileService1
(或更好的接口(interface))进行依赖注入(inject),然后轻松模拟它:
//declaring interface
protocol MobileServiceContracts: class {
static func Contract1(request: Bar, callback: (Foo) -> ())
}
//make implementation to conform to 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(...)
}
}
现在您可以轻松更改测试中的服务:
class MockedMobileService1: MobileServiceContracts
{
static func Contract1(request: Bar, callback: (Foo) -> ()) {
//do whatever with the mock
}
}
someWhereInTheCode(false, someObject: Bar(), serviceProvider: MockedMobileService1.self)
最好的部分是使用默认值你仍然可以用旧的方式调用它(而不是阻止更改):
someWhereInTheCode(false, someObject: Bar())
关于Swift 模拟类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30761536/