Created
September 14, 2017 14:18
-
-
Save victorpimentel/4ff341fec1b7e50e8d58ed1f76115778 to your computer and use it in GitHub Desktop.
OCMockitoBridge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import OCHamcrest; | |
NS_ASSUME_NONNULL_BEGIN | |
@interface HCArgumentCaptor (OCMockitoBridge) | |
- (NSObject *)tm_objectValue; | |
@end | |
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "HCArgumentCaptor+OCMockitoBridge.h" | |
@implementation HCArgumentCaptor (OCMockitoBridge) | |
- (NSObject *)tm_objectValue | |
{ | |
return [self value]; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@class MKTObjectMock; | |
@class MKTOngoingStubbing; | |
NS_ASSUME_NONNULL_BEGIN | |
MKTOngoingStubbing *TUMKTGivenWithLocation(id testCase, const char *fileName, int lineNumber); | |
MKTObjectMock *TUMKTVerifyCountWithLocation(id mock, id mode, id testCase, const char *fileName, int lineNumber); | |
id TUMKTTimes(NSUInteger wantedNumberOfInvocations); | |
id TUMKTNever(void); | |
id TUMKTAtLeast(NSUInteger minNumberOfInvocations); | |
id TUMKTAtLeastOnce(void); | |
NSObject *TUHC_anything(void); | |
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "OCMockitoBridge.h" | |
@import OCHamcrest; | |
@import OCMockito; | |
#import "HCArgumentCaptor+OCMockitoBridge.h" | |
MKTOngoingStubbing *TUMKTGivenWithLocation(id testCase, const char *fileName, int lineNumber) | |
{ | |
return MKTGivenWithLocation(testCase, fileName, lineNumber); | |
} | |
MKTObjectMock *TUMKTVerifyCountWithLocation(id mock, id mode, id testCase, const char *fileName, int lineNumber) | |
{ | |
return MKTVerifyCountWithLocation(mock, mode, testCase, fileName, lineNumber); | |
} | |
id TUMKTTimes(NSUInteger wantedNumberOfInvocations) | |
{ | |
return MKTTimes(wantedNumberOfInvocations); | |
} | |
id TUMKTNever(void) | |
{ | |
return MKTNever(); | |
} | |
id TUMKTAtLeast(NSUInteger minNumberOfInvocations) | |
{ | |
return MKTAtLeast(minNumberOfInvocations); | |
} | |
id TUMKTAtLeastOnce(void) | |
{ | |
return MKTAtLeast(1); | |
} | |
NSObject *TUHC_anything(void) | |
{ | |
return HC_anything(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import OCHamcrest | |
import OCMockito | |
import XCTest | |
extension NSObject { | |
class func mockObject() -> Self { | |
return unsafeBitCast(MKTObjectMock(with: self as AnyClass), to: self) | |
} | |
} | |
extension XCTestCase { | |
func given<T>(_ methodCall: @autoclosure () -> T, file: String = #file, line: Int = #line) -> MKTOngoingStubbing { | |
_ = methodCall() | |
return TUMKTGivenWithLocation(self, copyPointerFromString(file), Int32(line)) | |
} | |
func verify<T: AnyObject>(_ mock: T, times: UInt = 1, captor: HCArgumentCaptor? = nil, forArgument argument: UInt = 0, file: String = #file, line: Int = #line) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTTimes(times), self, copyPointerFromString(file), Int32(line)) | |
if let captor = captor { | |
unsafeBitCast(verifiedMock, to: MKTOngoingStubbing.self).withMatcher(captor, forArgument: argument) | |
} | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verify<T: AnyObject>(_ mock: T, times: UInt = 1, ignoringArgumentAt argument: UInt, file: String = #file, line: Int = #line) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTTimes(times), self, copyPointerFromString(file), Int32(line)) | |
unsafeBitCast(verifiedMock, to: MKTOngoingStubbing.self).withMatcher(TUHC_anything() as! HCMatcher, forArgument: argument) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verify<T: AnyObject>(_ mock: T, times: UInt = 1, file: String = #file, line: Int = #line, configuration: (MKTOngoingStubbing) -> Void) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTTimes(times), self, copyPointerFromString(file), Int32(line)) | |
configuration(unsafeBitCast(verifiedMock, to: MKTOngoingStubbing.self)) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verifyNever<T: AnyObject>(_ mock: T, file: String = #file, line: Int = #line) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTNever(), self, copyPointerFromString(file), Int32(line)) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verifyNever<T: AnyObject>(_ mock: T, file: String = #file, line: Int = #line, configuration: (MKTOngoingStubbing) -> Void) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTNever(), self, copyPointerFromString(file), Int32(line)) | |
configuration(unsafeBitCast(verifiedMock, to: MKTOngoingStubbing.self)) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verifyNever<T: AnyObject>(_ mock: T, ignoringArgumentAt argument: UInt, file: String = #file, line: Int = #line) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTNever(), self, copyPointerFromString(file), Int32(line)) | |
unsafeBitCast(verifiedMock, to: MKTOngoingStubbing.self).withMatcher(TUHC_anything() as! HCMatcher, forArgument: argument) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verifyAtLeast<T: AnyObject>(_ mock: T, times: UInt, file: String = #file, line: Int = #line) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTAtLeast(times), self, copyPointerFromString(file), Int32(line)) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
func verifyAtLeastOnce<T: AnyObject>(_ mock: T, file: String = #file, line: Int = #line) -> T { | |
let verifiedMock = TUMKTVerifyCountWithLocation(mock, TUMKTAtLeastOnce(), self, copyPointerFromString(file), Int32(line)) | |
return unsafeBitCast(verifiedMock, to: T.self) | |
} | |
} | |
extension HCArgumentCaptor { | |
func typedBlock<T>() -> T { | |
return unsafeBitCast(tm_objectValue(), to: T.self) | |
} | |
func typedValue<T: NSObjectProtocol>() -> T { | |
return unsafeBitCast(tm_objectValue(), to: T.self) | |
} | |
@nonobjc | |
func typedValue() -> String { | |
return tm_objectValue() as! String | |
} | |
@nonobjc | |
func typedValue() -> UUID { | |
return tm_objectValue() as! UUID | |
} | |
func typedValue<T>() -> [T] { | |
return tm_objectValue() as! [T] | |
} | |
func typedValue<T, U>() -> [T: U] { | |
return tm_objectValue() as! [T: U] | |
} | |
} | |
func mockProtocol<T>(_ aProtocol: T.Type) -> T { | |
let protocolName = String(describing: aProtocol) | |
let objcProtocol = searchObjCProtocol(withName: protocolName) | |
return unsafeBitCast(MKTProtocolMock(with: objcProtocol, includeOptionalMethods: true), to: T.self) | |
} | |
func mockProtocolWithoutOptionals<T>(_ aProtocol: T.Type) -> T { | |
let protocolName = String(describing: aProtocol) | |
let objcProtocol = searchObjCProtocol(withName: protocolName) | |
return unsafeBitCast(MKTProtocolMock(with: objcProtocol, includeOptionalMethods: false), to: T.self) | |
} | |
private func searchObjCProtocol(withName name: String) -> Protocol { | |
if let objcProtocol = objc_getProtocol(name) { | |
return objcProtocol | |
} | |
if let objcProtocol = objc_getProtocol("Tuenti.\(name)") { | |
return objcProtocol | |
} | |
if let objcProtocol = objc_getProtocol("CoreKit.\(name)") { | |
return objcProtocol | |
} | |
fatalError("Cannot find protocol '\(name)'") | |
} | |
func anything<T: NSObjectProtocol>() -> T { | |
return unsafeBitCast(TUHC_anything(), to: T.self) | |
} | |
func anything<T>() -> T? { | |
return .none | |
} | |
func anything() -> String { | |
return "" | |
} | |
func anything() -> UUID { | |
return UUID() | |
} | |
func anything<T>() -> [T] { | |
return [] | |
} | |
func anything<T, U>() -> [T: U] { | |
return [:] | |
} | |
func anything<T, U>() -> (T) -> U { | |
return { _ in | |
if U.self == Void.self { | |
return unsafeBitCast((), to: U.self) | |
} else { | |
return unsafeBitCast(TUHC_anything(), to: U.self) | |
} | |
} | |
} | |
func matchAnything() -> HCMatcher { | |
return TUHC_anything() as! HCMatcher | |
} | |
func ArgumentCaptor() -> HCArgumentCaptor { | |
return HCArgumentCaptor() | |
} | |
private func copyPointerFromString(_ string: String) -> UnsafeMutablePointer<Int8> { | |
// OCMockito needs a const char *, we have a String | |
// Automatic conversion do not work for us since ARC destroys the pointer when we want to use it | |
// Yeah, this means we are creating a memory leak, but this is just for testing so... | |
return UnsafeMutablePointer(mutating: (string as NSString).utf8String!) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment