UNPKG

typemoq

Version:

A simple mocking library for TypeScript

167 lines (131 loc) 5.56 kB
import * as _ from "lodash"; import * as all from "./_all"; import { MockBase } from "./MockBase"; import { InterceptorSetup } from "./InterceptorSetup"; import { Consts } from "./Consts"; export class MethodCall<T, TResult> implements all.IProxyCall<T>, all.IVerifies { protected _id: string; protected _setupCall: all.ICallContext; protected _setupCallback: all.IAction; protected _isVerifiable: boolean; protected _expectedCallCount: all.Times; protected _expectedCallType: all.ExpectedCallType; protected _isInvoked: boolean; protected _callCount: number = 0; protected _thrownException: Error; protected _evaluatedSuccessfully: boolean; protected constructor( public mock: MockBase<T>, private _setupExpression: all.IFunc2<T, TResult>, interceptor: InterceptorSetup<T>, proxy: T) { this._id = this.generateId(); _setupExpression(proxy); if (interceptor.interceptedCall) { let ic = interceptor.interceptedCall; let newArgs = this.transformToMatchers(ic.args); Object.defineProperty(newArgs, "callee", { configurable: true, enumerable: true, writable: false, value: ic.args.callee }); ic.args = <IArguments><any>newArgs; this._setupCall = ic; } else { throw new all.MockException(all.MockExceptionReason.InvalidSetup, this._setupExpression, `'${this._setupExpression}'`); } } static ofStaticMock<U, UResult>(mock: MockBase<U>, setupExpression: all.IFunc2<U, UResult>) { let interceptor = new InterceptorSetup<U>(); let proxy = all.ProxyFactory.createProxy<U>(mock.target, interceptor); let result = new MethodCall(mock, setupExpression, interceptor, proxy); return result; } static ofDynamicMock<U, UResult>(mock: MockBase<U>, setupExpression: all.IFunc2<U, UResult>) { let interceptor = new InterceptorSetup<U>(); let proxy = all.ProxyFactory.createProxyES6<U>(mock.target, interceptor); let result = new MethodCall(mock, setupExpression, interceptor, proxy); return result; } private generateId() { return "MethodCall<" + _.uniqueId() + ">"; } private transformToMatchers(args: IArguments): Array<all.IMatch> { let newArgs: Array<all.IMatch> = []; _.each(args, (a: any) => { if (!_.isObject(a)) { let newArg = new all.MatchValue(a); newArgs.push(newArg); } else { if (all.Match.isMatcher(a)) { newArgs.push(<all.IMatch>a); } else { // assume strict equality, short form of It.is(x => _.isEqual(x, a)) let newArg = new all.MatchPred(x => _.isEqual(x, a)); newArgs.push(newArg); } } }); return newArgs; } // IProxyCall get id(): string { return this._id; } get setupExpression(): all.IAction1<T> { return this._setupExpression; } get setupCall(): all.ICallContext { return this._setupCall; } get isVerifiable(): boolean { return this._isVerifiable; } get isInSequence(): boolean { return this._expectedCallType === all.ExpectedCallType.InSequence; } get expectedCallCount(): all.Times { return this._expectedCallCount; } get isInvoked(): boolean { return this._isInvoked; } get callCount(): number { return this._callCount; } setVerifiable( times: all.Times = all.Times.once(), expectedCallType: all.ExpectedCallType = all.ExpectedCallType.InAnyOrder): void { this._isVerifiable = true; this._expectedCallCount = times; this._expectedCallType = expectedCallType; } evaluatedSuccessfully() { this._evaluatedSuccessfully = true; } matches(call: all.ICallContext): boolean { let match = false; if (this._setupCall.property && call && call.property && this._setupCall.property.name === call.property.name) { if (this._setupCall.args.length >= call.args.length) { match = true; if (!call.isAnUnknownDynamicCallAtExecution) { _.each(this._setupCall.args, (x: any, index: number) => { let setupArg = <all.IMatch>x; let callArg = call.args[index]; if (match && !setupArg.___matches(callArg)) match = false; }); } } } return match; } execute(call: all.ICallContext): void { this._isInvoked = true; if (this._setupCallback != null) { this._setupCallback.apply(this, call.args); } if (this._thrownException != null) { throw this._thrownException; } this._callCount++; } // IVerifies verifiable( times?: all.Times, expectedCallType?: all.ExpectedCallType): void { this.setVerifiable(times, expectedCallType); } toString(): string { let res = `${this.setupCall}`; if (this.expectedCallCount) res = `${res}, ${this.expectedCallCount}`; return res; } }