Skip to content

Commit

Permalink
add not() matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
cakeinpanic committed Jan 29, 2018
1 parent 8c542fb commit 32bd8d8
Show file tree
Hide file tree
Showing 18 changed files with 170 additions and 81 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ foo.getBar(3);
// Call count verification
verify(mockedFoo.getBar(1)).once(); // was called with arg === 1 only once
verify(mockedFoo.getBar(2)).twice(); // was called with arg === 2 exactly two times
verify(mockedFoo.getBar(strictEqual(2).not())).once(); // was called with anything except 2 once
verify(mockedFoo.getBar(not().strictEqual(2))).once(); // was called with anything except 2 once
verify(mockedFoo.getBar(between(2, 3))).thrice(); // was called with arg beween 2-3 exactly three times
verify(mockedFoo.getBar(anyNumber()).times(4); // was called with any number arg exactly four times
verify(mockedFoo.getBar(anyNumber.not()).times(4); // was called with anything but not a number exactly four times
verify(mockedFoo.getBar(not().anyNumber).times(4); // was called with anything but not a number exactly four times
verify(mockedFoo.matchString(/param\d+/)).once(); // was once called with arg matching regexp
verify(mockedFoo.getBar(2)).atLeast(2); // was called with arg === 2 min two times
verify(mockedFoo.getBar(1)).atMost(1); // was called with arg === 1 max one time
verify(mockedFoo.getBar(4)).never(); // was never called with arg === 4
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Matcher} from "./Matcher";

export class MatchingStringMatcher extends Matcher {
export class MatchStringMatcher extends Matcher {
constructor(private expectedValue: any) {
super();
}
Expand Down
11 changes: 4 additions & 7 deletions src/matcher/type/Matcher.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as _ from "lodash";

export class Matcher {
public isNot: boolean = false;
private isNot: boolean = false;

public match(...values: any[]): boolean {
return this.reverseResult(false);
Expand All @@ -11,10 +9,9 @@ export class Matcher {
return `${this.prefix}`;
}

public not() {
const newMatcher = _.cloneDeep(this);
newMatcher.isNot = true;
return newMatcher;
public reverse() {
this.isNot = true;
return this;
}

protected get prefix(): string {
Expand Down
60 changes: 60 additions & 0 deletions src/matcher/type/Not.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {AnyFunctionMatcher} from "./AnyFunctionMatcher";
import {AnyNumberMatcher} from "./AnyNumberMatcher";
import {AnyOfClassMatcher} from "./AnyOfClassMatcher";
import {AnyStringMatcher} from "./AnyStringMatcher";
import {AnythingMatcher} from "./AnythingMatcher";
import {BetweenMatcher} from "./BetweenMatcher";
import {DeepEqualMatcher} from "./DeepEqualMatcher";
import {Matcher} from "./Matcher";
import {MatchStringMatcher} from "./MatchStringMatcher";
import {NotNullMatcher} from "./NotNullMatcher";
import {ObjectContainingMatcher} from "./ObjectContainingMatcher";
import {StrictEqualMatcher} from "./StrictEqualMatcher";

export class Not {

public anyOfClass<T>(expectedClass: {new (...args: any[]): T}): Matcher {
return (new AnyOfClassMatcher<T>(expectedClass)).reverse();
}

public anyFunction(): Matcher {
return (new AnyFunctionMatcher()).reverse();
}

public anyNumber(): Matcher {
return (new AnyNumberMatcher()).reverse();
}

public anyString(): Matcher {
return (new AnyStringMatcher()).reverse();
}

public anything(): Matcher {
return (new AnythingMatcher()).reverse();
}

public between(min: number, max: number): Matcher {
return (new BetweenMatcher(min, max)).reverse();
}

public deepEqual(expectedValue: any): Matcher {
return (new DeepEqualMatcher(expectedValue)).reverse();
}

public notNull(): Matcher {
return (new NotNullMatcher()).reverse();
}

public strictEqual(expectedValue: any): Matcher {
return (new StrictEqualMatcher(expectedValue)).reverse();
}

public matchString(expectedValue: string | RegExp): Matcher {
return (new MatchStringMatcher(expectedValue)).reverse();
}

public objectContaining(expectedValue: Object): Matcher {
return (new ObjectContainingMatcher(expectedValue)).reverse();
}

}
15 changes: 10 additions & 5 deletions src/ts-mockito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {AnythingMatcher} from "./matcher/type/AnythingMatcher";
import {BetweenMatcher} from "./matcher/type/BetweenMatcher";
import {DeepEqualMatcher} from "./matcher/type/DeepEqualMatcher";
import {Matcher} from "./matcher/type/Matcher";
import {MatchingStringMatcher} from "./matcher/type/MatchingStringMatcher";
import {MatchStringMatcher} from "./matcher/type/MatchStringMatcher";
import {Not} from "./matcher/type/Not";
import {NotNullMatcher} from "./matcher/type/NotNullMatcher";
import {ObjectContainingMatcher} from "./matcher/type/ObjectContainingMatcher";
import {StrictEqualMatcher} from "./matcher/type/StrictEqualMatcher";
Expand All @@ -33,7 +34,7 @@ export function spy<T>(instanceToSpy: T): T {
return new Spy(instanceToSpy).getMock();
}

export function mock<T>(clazz: { new(...args: any[]): T; } | (Function & { prototype: T }) ): T {
export function mock<T>(clazz: {new(...args: any[]): T; } | (Function & {prototype: T})): T {
return new Mocker(clazz).getMock();
}

Expand Down Expand Up @@ -78,7 +79,7 @@ export function resetCalls<T>(mockedValue: T): void {
(mockedValue as any).__tsmockitoMocker.resetCalls();
}

export function anyOfClass<T>(expectedClass: { new (...args: any[]): T }): any {
export function anyOfClass<T>(expectedClass: {new (...args: any[]): T}): any {
return new AnyOfClassMatcher(expectedClass) as any;
}

Expand Down Expand Up @@ -114,14 +115,18 @@ export function strictEqual(expectedValue: any): Matcher {
return new StrictEqualMatcher(expectedValue);
}

export function match(expectedValue: RegExp | string): Matcher {
return new MatchingStringMatcher(expectedValue);
export function matchString(expectedValue: RegExp | string): Matcher {
return new MatchStringMatcher(expectedValue);
}

export function objectContaining(expectedValue: Object): Matcher {
return new ObjectContainingMatcher(expectedValue);
}

export function not(): Not {
return new Not();
}

import * as mockito from "./ts-mockito";

export default mockito;
2 changes: 1 addition & 1 deletion src/utils/MockableFunctionsFinder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Looking for all function calls and declarations and provides an array of their names. The mechanism is greedy
* and tries to match as many function names as it can find and not only those of inspecting class.
* and tries to matchString as many function names as it can find and not only those of inspecting class.
*
* Matching occurrences are:
* - [.]functionName(
Expand Down
14 changes: 8 additions & 6 deletions test/matcher/type/AnyFunctionMatcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import {Matcher} from "../../../src/matcher/type/Matcher";
import {anyFunction} from "../../../src/ts-mockito";
import {anyFunction, not} from "../../../src/ts-mockito";

describe("AnyFunctionMatcher", () => {
let testObj: Matcher;
let notTestObj: Matcher;

beforeEach(() => {
testObj = anyFunction();
notTestObj = not().anyFunction();
});

describe("checking if function is function", () => {
it("returns true", () => {
// when
const result = testObj.match(() => "arbitrary return value");
const notResult = testObj.not().match(() => "arbitrary return value");
const notResult = notTestObj.match(() => "arbitrary return value");

// then
expect(result).toBeTruthy();
Expand All @@ -24,7 +26,7 @@ describe("AnyFunctionMatcher", () => {
it("returns false", () => {
// when
const result = testObj.match("some string");
const notResult = testObj.not().match("some string");
const notResult = notTestObj.match("some string");

// then
expect(result).toBeFalsy();
Expand All @@ -36,7 +38,7 @@ describe("AnyFunctionMatcher", () => {
it("returns false", () => {
// when
const result = testObj.match(5);
const notResult = testObj.not().match(5);
const notResult = notTestObj.match(5);

// then
expect(result).toBeFalsy();
Expand All @@ -48,7 +50,7 @@ describe("AnyFunctionMatcher", () => {
it("returns false", () => {
// when
const result = testObj.match({prop1: "prop1Value"});
const notResult = testObj.not().match({prop1: "prop1Value"});
const notResult = notTestObj.match({prop1: "prop1Value"});

// then
expect(result).toBeFalsy();
Expand All @@ -60,7 +62,7 @@ describe("AnyFunctionMatcher", () => {
it("returns 'anyFunction()'", () => {
// when
const result = testObj.toString();
const notResult = testObj.not().toString();
const notResult = notTestObj.toString();

// then
expect(result).toEqual("anyFunction()");
Expand Down
14 changes: 8 additions & 6 deletions test/matcher/type/AnyNumberMatcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import {Matcher} from "../../../src/matcher/type/Matcher";
import {anyNumber} from "../../../src/ts-mockito";
import {anyNumber, not} from "../../../src/ts-mockito";

describe("AnyNumberMatcher", () => {
let testObj: Matcher;
let notTestObj: Matcher;

beforeEach(() => {
testObj = anyNumber();
notTestObj = not().anyNumber();
});

describe("checking if positive number is matching", () => {
it("returns true", () => {
// when
const result = testObj.match(3);
const notResult = testObj.not().match(3);
const notResult = notTestObj.match(3);

// then
expect(result).toBeTruthy();
Expand All @@ -24,7 +26,7 @@ describe("AnyNumberMatcher", () => {
it("returns true", () => {
// when
const result = testObj.match(-3);
const notResult = testObj.not().match(-3);
const notResult = notTestObj.match(-3);

// then
expect(result).toBeTruthy();
Expand All @@ -36,7 +38,7 @@ describe("AnyNumberMatcher", () => {
it("returns true", () => {
// when
const result = testObj.match(0);
const notResult = testObj.not().match(0);
const notResult = notTestObj.match(0);

// then
expect(result).toBeTruthy();
Expand All @@ -48,7 +50,7 @@ describe("AnyNumberMatcher", () => {
it("returns false", () => {
// when
const result = testObj.match("5");
const notResult = testObj.not().match("5");
const notResult = notTestObj.match("5");

// then
expect(result).toBeFalsy();
Expand All @@ -60,7 +62,7 @@ describe("AnyNumberMatcher", () => {
it("returns false", () => {
// when
const result = testObj.match({});
const notResult = testObj.not().match({});
const notResult = notTestObj.match({});

// then
expect(result).toBeFalsy();
Expand Down
14 changes: 8 additions & 6 deletions test/matcher/type/AnyOfClassMatcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {Matcher} from "../../../src/matcher/type/Matcher";
import {anyOfClass} from "../../../src/ts-mockito";
import {anyOfClass, not} from "../../../src/ts-mockito";

describe("AnyOfClassMatcher", () => {
let testObj: Matcher;
let notTestObj: Matcher;

class Car {
constructor() {
Expand All @@ -11,6 +12,7 @@ describe("AnyOfClassMatcher", () => {

beforeEach(() => {
testObj = anyOfClass(Car);
notTestObj = not().anyOfClass(Car);
});

describe("checking if class matches", () => {
Expand All @@ -19,7 +21,7 @@ describe("AnyOfClassMatcher", () => {

// when
const result = testObj.match(value);
const notResult = testObj.not().match(value);
const notResult = notTestObj.match(value);

// then
expect(result).toBeTruthy();
Expand All @@ -33,7 +35,7 @@ describe("AnyOfClassMatcher", () => {

// when
const result = testObj.match(value);
const notResult = testObj.not().match(value);
const notResult = notTestObj.match(value);

// then
expect(result).toBeFalsy();
Expand All @@ -52,13 +54,13 @@ describe("AnyOfClassMatcher", () => {
});
});

describe("checking if different classes match", () => {
describe("checking if different classes matchString", () => {
it("returns false", () => {
const value = "a string";

// when
const result = testObj.match(value);
const notResult = testObj.not().match(value);
const notResult = notTestObj.match(value);

// then
expect(result).toBeFalsy();
Expand All @@ -69,7 +71,7 @@ describe("AnyOfClassMatcher", () => {
describe("checking if toString works", () => {
it("returns 'anyOfClass(Car)'", () => {
const result = testObj.toString();
const notResult = testObj.not().toString();
const notResult = notTestObj.toString();

// then
expect(result).toEqual("anyOfClass(Car)");
Expand Down
12 changes: 7 additions & 5 deletions test/matcher/type/AnyStringMatcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import {Matcher} from "../../../src/matcher/type/Matcher";
import {anyString} from "../../../src/ts-mockito";
import {anyString, not} from "../../../src/ts-mockito";

describe("AnyStringMatcher", () => {
let testObj: Matcher;
let notTestObj: Matcher;

beforeEach(() => {
testObj = anyString();
notTestObj = not().anyString();
});

describe("checking if number matches", () => {
it("returns false", () => {
// when
const result = testObj.match(3);
const notResult = testObj.not().match(3);
const notResult = notTestObj.match(3);

// then
expect(result).toBeFalsy();
Expand All @@ -25,7 +27,7 @@ describe("AnyStringMatcher", () => {

// when
const result = testObj.match({});
const notResult = testObj.not().match({});
const notResult = notTestObj.match({});

// then
expect(result).toBeFalsy();
Expand All @@ -37,7 +39,7 @@ describe("AnyStringMatcher", () => {
it("returns true", () => {
// when
const result = testObj.match("");
const notResult = testObj.not().match("");
const notResult = notTestObj.match("");

// then
expect(result).toBeTruthy();
Expand All @@ -49,7 +51,7 @@ describe("AnyStringMatcher", () => {
it("returns true", () => {
// when
const result = testObj.match("sampleString");
const notResult = testObj.not().match("sampleString");
const notResult = notTestObj.match("sampleString");

// then
expect(result).toBeTruthy();
Expand Down
Loading

0 comments on commit 32bd8d8

Please sign in to comment.