Skip to content

Instantly share code, notes, and snippets.

@victorpimentel
Created September 14, 2017 14:18
Show Gist options
  • Save victorpimentel/4ff341fec1b7e50e8d58ed1f76115778 to your computer and use it in GitHub Desktop.
Save victorpimentel/4ff341fec1b7e50e8d58ed1f76115778 to your computer and use it in GitHub Desktop.
OCMockitoBridge
@import OCHamcrest;
NS_ASSUME_NONNULL_BEGIN
@interface HCArgumentCaptor (OCMockitoBridge)
- (NSObject *)tm_objectValue;
@end
NS_ASSUME_NONNULL_END
#import "HCArgumentCaptor+OCMockitoBridge.h"
@implementation HCArgumentCaptor (OCMockitoBridge)
- (NSObject *)tm_objectValue
{
return [self value];
}
@end
#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
#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();
}
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