子类化 Typhoon 程序集以覆盖不起作用的方法
Subclassing a Typhoon assembly to override methods not working
我正在对 Typhoon 程序集进行子class,以便 return 对存根实现进行单元测试。
我的程序集看起来像这样:
class RealAssembly : TyphoonAssembly {
public dynamic func instanceToStubOut() -> AnyObject {
return TyphoonDefinition.withClass(SomeRealWorldClass.self)
}
public dynamic func instanceToTest() -> AnyObject {
return TyphoonDefinition.withClass(ClassToTest.self, configuration: { (definition : TyphoonDefinition!) -> Void in
definition.useInitializer("initWithObjectToStub:", parameters: { (initializer : TyphoonMethod!) -> Void in
initializer.injectParameterWith(self.instancetoStubOut())
})
})
}
}
我的测试 class 仅用于测试类型 ClassToTest
的实例,我想使用对类型 SomeRealWorldClass
的对象的初始化程序注入依赖项进行测试被淘汰了。所以我 subclass RealAssembly 以便 instanceToStubOut()
被覆盖到 return 我的存根对象。
class MyTestClass : XCTestCase {
var assembly : TestAssembly!
class TestAssembly : RealAssembly {
override dynamic func instanceToStubOut() -> AnyObject {
return TyphoonDefinition.withClass(TestClass.self)
}
}
@objc
class TestClass : NSObject, ClassToStubOut {
func methodToStubOut() { /* do nothing */ }
}
override func setUp() {
super.setUp()
self.assembly = TestAssembly().activate()
}
override func tearDown() {
self.assembly = nil
super.tearDown()
}
func testStuff() {
let testingInstance = self.assembly.instanceToTest()
XCTAssertTrue(testingInstance.doStuff(), "doStuff returns true")
}
}
我原以为这会起作用,但它不起作用。台风似乎注入了一个未初始化的对象,而不是调用 TestAssembly.instanceToStubOut()
我是不是做错了什么?我应该采取不同的方法吗?
编辑:这里有一些代码,您可以将其粘贴到演示问题的 Swift 游乐场中。最后一行显示 c.otherInstance
returning nil
:
import Typhoon
@objc
class BaseClass : NSObject {
var otherInstance : OtherProtocol!
func doIt() -> String {
return self.otherInstance.doStuff()
}
}
@objc
protocol OtherProtocol {
func doStuff() -> String
}
@objc
class OtherImpl : NSObject, OtherProtocol {
func doStuff() -> String {
return "OtherClass"
}
}
@objc
class StubClass : NSObject, OtherProtocol {
func doStuff() -> String {
return "Stubbed out"
}
}
class BaseAssembly : TyphoonAssembly {
dynamic func baseObject() -> AnyObject {
return TyphoonDefinition.withClass(BaseClass.self,
configuration: { (def : TyphoonDefinition!) -> Void in
def.injectProperty("otherInstance", with: self.otherObject())
})
}
dynamic func otherObject() -> AnyObject {
return TyphoonDefinition.withClass(OtherImpl.self)
}
}
var assembly = BaseAssembly()
assembly.activate()
var b = assembly.baseObject() as! BaseClass
b.doIt()
@objc
class TestAssembly : BaseAssembly {
override func otherObject() -> AnyObject {
return TyphoonDefinition.withClass(StubClass.self)
}
}
var testAssembly = TestAssembly()
testAssembly.activate()
var c = testAssembly.baseObject() as! BaseClass
c.otherInstance // this shouldn't be nil
编辑:
虽然打补丁是一种选择,如下面@Herman 的回答所述,问题中尝试的是受支持的功能,但是存在一个回归错误,无法正常工作。
回归错误已在 Typhoon 3.2.2 中修复,因此现在修补和覆盖程序集再次成为针对特定用例配置 Typhoon 的选项。
正在修补
Typhoon 中有一个用于此目的的修补功能。看here。
例如:
class StubClass : NSObject, OtherProtocol {
@objc func doStuff() -> String {
return "Stubbed out"
}
}
let assembly = BaseAssembly()
assembly.activate()
let b = assembly.baseObject() as! BaseClass
print(b.doIt())
let testAssembly = BaseAssembly().activate()
let patcher = TyphoonPatcher()
patcher.patchDefinitionWithSelector("otherObject") { () -> AnyObject! in
return StubClass()
}
testAssembly.attachPostProcessor(patcher)
let c = testAssembly.baseObject() as! BaseClass
print(c.doIt())
我正在对 Typhoon 程序集进行子class,以便 return 对存根实现进行单元测试。
我的程序集看起来像这样:
class RealAssembly : TyphoonAssembly {
public dynamic func instanceToStubOut() -> AnyObject {
return TyphoonDefinition.withClass(SomeRealWorldClass.self)
}
public dynamic func instanceToTest() -> AnyObject {
return TyphoonDefinition.withClass(ClassToTest.self, configuration: { (definition : TyphoonDefinition!) -> Void in
definition.useInitializer("initWithObjectToStub:", parameters: { (initializer : TyphoonMethod!) -> Void in
initializer.injectParameterWith(self.instancetoStubOut())
})
})
}
}
我的测试 class 仅用于测试类型 ClassToTest
的实例,我想使用对类型 SomeRealWorldClass
的对象的初始化程序注入依赖项进行测试被淘汰了。所以我 subclass RealAssembly 以便 instanceToStubOut()
被覆盖到 return 我的存根对象。
class MyTestClass : XCTestCase {
var assembly : TestAssembly!
class TestAssembly : RealAssembly {
override dynamic func instanceToStubOut() -> AnyObject {
return TyphoonDefinition.withClass(TestClass.self)
}
}
@objc
class TestClass : NSObject, ClassToStubOut {
func methodToStubOut() { /* do nothing */ }
}
override func setUp() {
super.setUp()
self.assembly = TestAssembly().activate()
}
override func tearDown() {
self.assembly = nil
super.tearDown()
}
func testStuff() {
let testingInstance = self.assembly.instanceToTest()
XCTAssertTrue(testingInstance.doStuff(), "doStuff returns true")
}
}
我原以为这会起作用,但它不起作用。台风似乎注入了一个未初始化的对象,而不是调用 TestAssembly.instanceToStubOut()
我是不是做错了什么?我应该采取不同的方法吗?
编辑:这里有一些代码,您可以将其粘贴到演示问题的 Swift 游乐场中。最后一行显示 c.otherInstance
returning nil
:
import Typhoon
@objc
class BaseClass : NSObject {
var otherInstance : OtherProtocol!
func doIt() -> String {
return self.otherInstance.doStuff()
}
}
@objc
protocol OtherProtocol {
func doStuff() -> String
}
@objc
class OtherImpl : NSObject, OtherProtocol {
func doStuff() -> String {
return "OtherClass"
}
}
@objc
class StubClass : NSObject, OtherProtocol {
func doStuff() -> String {
return "Stubbed out"
}
}
class BaseAssembly : TyphoonAssembly {
dynamic func baseObject() -> AnyObject {
return TyphoonDefinition.withClass(BaseClass.self,
configuration: { (def : TyphoonDefinition!) -> Void in
def.injectProperty("otherInstance", with: self.otherObject())
})
}
dynamic func otherObject() -> AnyObject {
return TyphoonDefinition.withClass(OtherImpl.self)
}
}
var assembly = BaseAssembly()
assembly.activate()
var b = assembly.baseObject() as! BaseClass
b.doIt()
@objc
class TestAssembly : BaseAssembly {
override func otherObject() -> AnyObject {
return TyphoonDefinition.withClass(StubClass.self)
}
}
var testAssembly = TestAssembly()
testAssembly.activate()
var c = testAssembly.baseObject() as! BaseClass
c.otherInstance // this shouldn't be nil
编辑:
虽然打补丁是一种选择,如下面@Herman 的回答所述,问题中尝试的是受支持的功能,但是存在一个回归错误,无法正常工作。
回归错误已在 Typhoon 3.2.2 中修复,因此现在修补和覆盖程序集再次成为针对特定用例配置 Typhoon 的选项。
正在修补
Typhoon 中有一个用于此目的的修补功能。看here。
例如:
class StubClass : NSObject, OtherProtocol {
@objc func doStuff() -> String {
return "Stubbed out"
}
}
let assembly = BaseAssembly()
assembly.activate()
let b = assembly.baseObject() as! BaseClass
print(b.doIt())
let testAssembly = BaseAssembly().activate()
let patcher = TyphoonPatcher()
patcher.patchDefinitionWithSelector("otherObject") { () -> AnyObject! in
return StubClass()
}
testAssembly.attachPostProcessor(patcher)
let c = testAssembly.baseObject() as! BaseClass
print(c.doIt())