Added ParameterMatcher for (optional) throwing closures and optionals, e.g. anyThrowingClosure(), anyOptionalThrowingClosure and null()

Added Acceptance test for inheritance stubbing and verifying
This commit is contained in:
Arjan Duijzer 2017-12-29 14:04:44 +01:00
parent f0f31bd0e9
commit eaab7db26d
4 changed files with 240 additions and 20 deletions

View File

@ -45,6 +45,10 @@ public func anyString() -> ParameterMatcher<String> {
}
/// Returns a matcher matching any closure.
public func anyThrowingClosure<IN, OUT>() -> ParameterMatcher<(IN) throws -> OUT> {
return ParameterMatcher()
}
public func anyClosure<IN, OUT>() -> ParameterMatcher<(IN) -> OUT> {
return ParameterMatcher()
}
@ -97,9 +101,28 @@ public func anyClosure<IN, OUT>() -> ParameterMatcher<(((IN)) -> OUT)?> {
return notNil()
}
public func anyOptionalThrowingClosure<IN, OUT>() -> ParameterMatcher<(((IN)) throws -> OUT)?> {
return notNil()
}
/// Returns a matcher matching any non nil value.
public func notNil<T>() -> ParameterMatcher<T?> {
return ParameterMatcher {
if case .none = $0 { return false } else { return true }
if case .none = $0 {
return false
} else {
return true
}
}
}
/// Returns a matcher matching any nil value
public func isNil<T>() -> ParameterMatcher<T?> {
return ParameterMatcher {
if case .none = $0 {
return true
} else {
return false
}
}
}

View File

@ -54,11 +54,28 @@ class ParameterMatcherFunctionsTest: XCTestCase {
func testAny() {
XCTAssertTrue(any().matches(X()))
}
func testIsNil() {
let optional: X? = nil
XCTAssertTrue(isNil().matches(nil as X?))
XCTAssertTrue(isNil().matches(optional))
XCTAssertFalse(isNil().matches(X()))
}
func testAnyClosure() {
XCTAssertTrue(anyClosure().matches({ 0 }))
}
func testAnyThrowingClosure() {
XCTAssertTrue(anyThrowingClosure().matches({ 0 }))
XCTAssertTrue(anyThrowingClosure().matches({ (p: Int) throws in 1 }))
}
func testAnyOptionalThrowingClosure() {
XCTAssertTrue(anyOptionalThrowingClosure().matches({ (i: String) in 0 }))
XCTAssertTrue(anyOptionalThrowingClosure().matches({ (p: Int) throws in 1 }))
}
func testOptionalEqualToEquatable() {
XCTAssertTrue(equal(to: nil as Int?).matches(nil))
XCTAssertTrue(equal(to: 1 as Int?).matches(1))

View File

@ -56,19 +56,19 @@ class TestedSubclass: TestedClass, TestedProtocol {
return 0
}
func withThrowingClosure(closure: ((String)) throws -> String?) -> String? {
func withThrowingClosure(closure: (String) throws -> String?) -> String? {
return nil
}
func withThrowingClosureThrows(closure: ((String)) throws -> String?) throws -> String? {
func withThrowingClosureThrows(closure: (String) throws -> String?) throws -> String? {
return nil
}
func withThrowingEscapingClosure(closure: @escaping ((String)) throws -> String?) -> String? {
func withThrowingEscapingClosure(closure: @escaping (String) throws -> String?) -> String? {
return nil
}
func withThrowingOptionalClosureThrows(closure: (((String)) throws -> String?)?) throws -> String? {
func withThrowingOptionalClosureThrows(closure: ((String) throws -> String?)?) throws -> String? {
return nil
}
@ -80,3 +80,11 @@ class TestedSubclass: TestedClass, TestedProtocol {
return "c"
}
}
class TestedSubSubClass: TestedSubclass {
func subSubMethod() -> String? {
return nil
}
}

View File

@ -10,65 +10,65 @@ import XCTest
@testable import Cuckoo
class StubbingTest: XCTestCase {
func testMultipleReturns() {
let mock = MockTestedClass()
stub(mock) { mock in
when(mock.readOnlyProperty.get).thenReturn("a").thenReturn("b", "c")
}
XCTAssertEqual(mock.readOnlyProperty, "a")
XCTAssertEqual(mock.readOnlyProperty, "b")
XCTAssertEqual(mock.readOnlyProperty, "c")
XCTAssertEqual(mock.readOnlyProperty, "c")
}
func testOverrideStubWithMoreGeneralParameterMatcher() {
let mock = MockTestedClass()
stub(mock) { mock in
when(mock.count(characters: "a")).thenReturn(2)
when(mock.count(characters: anyString())).thenReturn(1)
}
XCTAssertEqual(mock.count(characters: "a"), 1)
}
func testOverrideStubWithMoreSpecificParameterMatcher() {
let mock = MockTestedClass()
stub(mock) { mock in
when(mock.count(characters: anyString())).thenReturn(1)
when(mock.count(characters: "a")).thenReturn(2)
}
XCTAssertEqual(mock.count(characters: "a"), 2)
}
func testUnstubbedSpy() {
let mock = MockTestedClass().withEnabledSuperclassSpy()
XCTAssertEqual(mock.count(characters: "a"), 1)
}
func testStubOfMultipleDifferentCalls() {
let mock = MockTestedClass()
stub(mock) { mock in
when(mock.readOnlyProperty.get).thenReturn("a")
when(mock.count(characters: "a")).thenReturn(1)
}
XCTAssertEqual(mock.readOnlyProperty, "a")
XCTAssertEqual(mock.count(characters: "a"), 1)
}
func testSubClass() {
let mock = MockTestedSubclass()
XCTAssertNotNil(mock)
stub(mock) { mock in
when(mock.readOnlyProperty.get).thenReturn("a").thenReturn("b", "c")
}
XCTAssertEqual(mock.readOnlyProperty, "a")
XCTAssertEqual(mock.readOnlyProperty, "b")
XCTAssertEqual(mock.readOnlyProperty, "c")
@ -93,6 +93,7 @@ class StubbingTest: XCTestCase {
XCTAssertNotNil(mock)
stub(mock) { mock in
when(mock.methodWithParameter(anyInt())).thenReturn("t1")
when(mock.methodWithParameter(anyString())).thenReturn("t")
}
@ -106,6 +107,7 @@ class StubbingTest: XCTestCase {
stub(mock) { mock in
when(mock.methodWithParameter(anyInt())).thenReturn("t1")
when(mock.methodWithParameter(anyString())).thenReturn("s1")
}
XCTAssertEqual(mock.methodWithParameter(1), "t1")
@ -123,4 +125,174 @@ class StubbingTest: XCTestCase {
XCTAssertEqual(mock.protocolMethod(), "a1")
}
func testSubclassWithGrandparentsInheritanceAcceptanceTest() {
let mock = MockTestedSubSubClass()
XCTAssertNotNil(mock)
var setReadWriteProperty: Int = -1
var setOptionalProperty = -1
var callNoReturn = false
var callNoReturnThrows = false
var callWithEscape = false
var callWithOptionalClosure = false
var callWithLabelAndUnderscore = false
// Mock all available functions
stub(mock) { stub in
// sub-sub class
when(stub.subSubMethod()).thenReturn("not nil")
// sub-class
when(stub.withImplicitlyUnwrappedOptional(i: anyInt())).thenReturn("implicit unwrapped return")
when(stub.withThrows()).thenReturn(10)
when(stub.withNamedTuple(tuple: any())).thenReturn(11)
when(stub.subclassMethod()).thenReturn(12)
when(stub.withOptionalClosureAndReturn(anyString(), closure: isNil())).thenReturn(2)
when(stub.withClosureAndParam(anyString(), closure: anyClosure())).thenReturn(3)
when(stub.withMultClosures(closure: anyClosure(), closureB: anyClosure(), closureC: anyClosure())).thenReturn(4)
when(stub.withThrowingClosure(closure: anyThrowingClosure())).thenReturn("throwing closure")
when(stub.withThrowingClosureThrows(closure: anyThrowingClosure())).thenReturn("closure throwing")
when(stub.withThrowingEscapingClosure(closure: anyThrowingClosure())).thenReturn("escaping closure")
when(stub.withThrowingOptionalClosureThrows(closure: anyOptionalThrowingClosure())).thenReturn("optional closure throwing")
when(stub.methodWithParameter(anyString())).thenReturn("parameter string")
when(stub.methodWithParameter(anyInt())).thenReturn("parameter int")
// class
when(stub.privateSetProperty.get).thenReturn(5)
when(stub.readOnlyProperty.get).thenReturn("b")
when(stub.readWriteProperty.set(anyInt())).then { i in
setReadWriteProperty = i
}
when(stub.readWriteProperty.get).thenReturn(7)
when(stub.optionalProperty.set(anyInt())).then { i in
setOptionalProperty = i!
}
when(stub.optionalProperty.get).thenReturn(8)
when(stub.noReturn()).then { _ in
callNoReturn = true
}
when(stub.count(characters: anyString())).thenReturn(9)
when(stub.withNoReturnThrows()).then { _ in
callNoReturnThrows = true
}
when(stub.withClosure(anyClosure())).thenReturn(14)
when(stub.withEscape(anyString(), action: anyClosure())).then { _ in
callWithEscape = true
}
when(stub.withOptionalClosure(anyString(), closure: anyClosure())).then { _ in
callWithOptionalClosure = true
}
when(stub.withLabelAndUnderscore(labelA: anyString(), anyString())).then { _ in
callWithLabelAndUnderscore = true
}
when(stub.callingCountCharactersMethodWithHello()).thenReturn(15)
// protocol
when(stub.protocolMethod()).thenReturn("protocol method")
}
//
// Test stubbing
XCTAssertEqual(mock.subSubMethod(), "not nil")
// sub-class
XCTAssertEqual(mock.withImplicitlyUnwrappedOptional(i: 0), "implicit unwrapped return")
XCTAssertEqual(try! mock.withThrows(), 10)
XCTAssertEqual(mock.withNamedTuple(tuple: (a: "A", b: "B")), 11)
XCTAssertEqual(mock.subclassMethod(), 12)
XCTAssertEqual(mock.withOptionalClosureAndReturn("a", closure: nil), 2)
XCTAssertEqual(mock.withClosureAndParam("a", closure: { _ in 0 }), 3)
XCTAssertEqual(mock.withMultClosures(closure: { _ in 0 }, closureB: { _ in 1 }, closureC: { _ in 2 }), 4)
XCTAssertEqual(mock.withThrowingClosure { p throws in
return nil
}, "throwing closure")
XCTAssertEqual(try! mock.withThrowingClosureThrows(closure: { _ in nil }), "closure throwing")
XCTAssertEqual(mock.withThrowingEscapingClosure(closure: { _ in nil }), "escaping closure")
XCTAssertEqual(try! mock.withThrowingOptionalClosureThrows(closure: { _ in nil }), "optional closure throwing")
XCTAssertEqual(mock.methodWithParameter("a"), "parameter string")
XCTAssertEqual(mock.methodWithParameter(1), "parameter int")
// class
XCTAssertEqual(mock.privateSetProperty, 5)
XCTAssertEqual(mock.readOnlyProperty, "b")
XCTAssertEqual({
mock.readWriteProperty = 100;
return setReadWriteProperty
}(), 100)
XCTAssertEqual(mock.readWriteProperty, 7)
XCTAssertEqual({
mock.optionalProperty = 200
return setOptionalProperty
}(), 200)
XCTAssertEqual(mock.optionalProperty, 8)
XCTAssertTrue({
mock.noReturn()
return callNoReturn
}())
XCTAssertEqual(mock.count(characters: "a"), 9)
XCTAssertTrue({
try! mock.withNoReturnThrows()
return callNoReturnThrows
}())
XCTAssertEqual(mock.withClosure { _ in
41
}, 14)
XCTAssertTrue({
mock.withEscape("a") { _ in }
return callWithEscape
}())
XCTAssertTrue({
mock.withOptionalClosure("a") { _ in }
return callWithOptionalClosure
}())
XCTAssertTrue({
mock.withLabelAndUnderscore(labelA: "labelA", "any")
return callWithLabelAndUnderscore
}())
XCTAssertEqual(mock.callingCountCharactersMethodWithHello(), 15)
// Protocol
XCTAssertEqual(mock.protocolMethod(), "protocol method")
//
// Test Verification
// sub-sub class
verify(mock, times(1)).subSubMethod()
// sub-class
verify(mock, times(1)).withImplicitlyUnwrappedOptional(i: anyInt())
verify(mock, times(1)).withThrows()
verify(mock, times(1)).withNamedTuple(tuple: any())
verify(mock, times(1)).subclassMethod()
verify(mock, times(1)).withOptionalClosureAndReturn(anyString(), closure: isNil())
verify(mock, times(1)).withClosureAndParam(anyString(), closure: anyClosure())
verify(mock, times(1)).withMultClosures(closure: anyClosure(), closureB: anyClosure(), closureC: anyClosure())
verify(mock, times(1)).withThrowingClosure(closure: anyThrowingClosure())
verify(mock, times(1)).withThrowingClosureThrows(closure: anyThrowingClosure())
verify(mock, times(1)).withThrowingEscapingClosure(closure: anyThrowingClosure())
verify(mock, times(1)).withThrowingOptionalClosureThrows(closure: anyOptionalThrowingClosure())
verify(mock, times(1)).methodWithParameter(anyString())
verify(mock, times(1)).methodWithParameter(anyInt())
// class
verify(mock, times(1)).privateSetProperty.get
verify(mock, times(1)).readOnlyProperty.get
verify(mock, times(1)).readWriteProperty.set(anyInt())
verify(mock, times(1)).readWriteProperty.get
verify(mock, times(1)).optionalProperty.set(anyInt())
verify(mock, times(1)).optionalProperty.get
verify(mock, times(1)).noReturn()
verify(mock, times(1)).count(characters: anyString())
verify(mock, times(1)).withNoReturnThrows()
verify(mock, times(1)).withClosure(anyClosure())
verify(mock, times(1)).withEscape(anyString(), action: anyClosure())
verify(mock, times(1)).withOptionalClosure(anyString(), closure: anyClosure())
verify(mock, times(1)).withLabelAndUnderscore(labelA: anyString(), anyString())
verify(mock, times(1)).callingCountCharactersMethodWithHello()
// protocol
verify(mock, times(1)).protocolMethod()
}
}