typemoq
Version:
A simple mocking library for TypeScript
167 lines (131 loc) • 5.56 kB
text/typescript
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;
}
}