Sono principalmente interessato alle risposte in merito a una lingua Swift, ma le risposte più generali sono sempre ben accette.
Voglio testare una classe (CUT), e per questo userò l'iniezione di dipendenza. Ora, posso:
- Crea un protocollo che verrà utilizzato dal mio CUT, a cui saranno conformi alcune classi concrete e alcune classi di stub.
- Basta usare la classe concreta nel mio CUT e avere una classe stub come sottoclasse della classe concreta. La classe Stub sostituirà solo i metodi che CUT sta utilizzando dalla classe concreta.
Esempio per l'opzione 1:
// PRODUCTION CODE
class A {
func incrementedValueOf(_ b: BProtocol) -> Int {
return b.value + 1
}
}
protocol BProtocol {
func value() -> Int
}
class B: BProtocol {
func value() -> Int { return calculateValueSomehow() }
func calculateValueSomehow() -> Int { return ... }
}
// TEST CODE
class BStub: BProtocol {
var valueToProvide: Int = 0
func value() -> Int { return valueToProvide }
}
class ATests: XCTestCase {
func testIncrementedValueOf() {
let bStub = BStub()
bStub.valueToProvide = 11
let a = A()
XCTAssertEqual(a.incrementedValueOf(bStub), bStub.valueToProvide + 1)
}
}
Esempio per l'opzione 2:
// PRODUCTION CODE
class A {
func incrementedValueOf(_ b: B) -> Int {
return b.value + 1
}
}
// Note: BProtocol is removed
class B {
func value() -> Int { return calculateValueSomehow() }
func calculateValueSomehow() -> Int { return ... }
}
// TEST CODE
class BStub: B {
var valueToProvide: Int = 0
override func value() -> Int { return valueToProvide }
// Note: calculateValueSomehow is not overridden
}
class ATests: XCTestCase {
func testIncrementedValueOf() {
let bStub = BStub()
bStub.valueToProvide = 11
let a = A()
XCTAssertEqual(a.incrementedValueOf(bStub), bStub.valueToProvide + 1)
}
}
C'è un lato negativo nell'usare l'opzione 2?
-
AeBsono più strettamente accoppiati? - C'è qualche problema se la classe
Bè una parte di un diverso framework? Forse sarà un problema in futuro Swift seAutilizza un metodo daBche èpublicma nonopen, quindi non sarà sovrascrivibile (ad esempiovalue())?