Skip to content

Commit 91182a9

Browse files
Tests refactoring and small improvements (#98)
* upgrade dependencies * minor refactoring and fix * remove redundant and duplicated tests * add specs * resolves and rejects spec * shorter import of index on specs * add important issues in comments on specs
1 parent 8b7fca1 commit 91182a9

27 files changed

+2985
-2841
lines changed

package-lock.json

Lines changed: 2421 additions & 2320 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
"license": "ISC",
1717
"devDependencies": {
1818
"@ava/typescript": "^1.1.0",
19-
"@types/node": "latest",
20-
"ava": "^3.3.0",
19+
"ava": "^3.7.0",
2120
"typescript": "^3.0.0"
2221
},
2322
"ava": {
@@ -30,7 +29,6 @@
3029
]
3130
},
3231
"cache": false,
33-
"concurrency": 1,
3432
"failFast": true,
3533
"failWithoutAssertions": true
3634
},

spec/Utilities.spec.ts

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,62 @@
11
import test from 'ava';
2+
3+
import { Arg } from '../src';
24
import { areArgumentArraysEqual } from '../src/Utilities';
3-
import { Arg } from '../src/index';
45

56
const testObject = { "foo": "bar" };
67
const testArray = ["a", 1, true];
7-
const testFunc = () => {};
8+
9+
// #90: Infinite recursion in deepEqual https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/blob/master/spec/issues/90.test.ts
10+
const parent = {} as any;
11+
parent.child = parent;
12+
const root = {} as any;
13+
root.path = { to: { nested: root } };
14+
15+
const testFunc = () => { };
816

917
//#region areArgumentArraysEqual
1018
test('areArgumentArraysEqual should return valid result for primitive arguments', t => {
1119
// single
12-
t.true(areArgumentArraysEqual([''],['']));
13-
t.true(areArgumentArraysEqual(['a'],['a']));
14-
t.true(areArgumentArraysEqual([0],[0]));
15-
t.true(areArgumentArraysEqual([1],[1]));
16-
t.true(areArgumentArraysEqual([true],[true]));
17-
t.true(areArgumentArraysEqual([false],[false]));
18-
t.true(areArgumentArraysEqual([undefined],[undefined]));
19-
t.true(areArgumentArraysEqual([null],[null]));
20-
t.true(areArgumentArraysEqual([testObject],[testObject]));
21-
t.true(areArgumentArraysEqual([testArray],[testArray]));
22-
t.true(areArgumentArraysEqual([testFunc],[testFunc]));
20+
t.true(areArgumentArraysEqual([''], ['']));
21+
t.true(areArgumentArraysEqual(['a'], ['a']));
22+
t.true(areArgumentArraysEqual([0], [0]));
23+
t.true(areArgumentArraysEqual([1], [1]));
24+
t.true(areArgumentArraysEqual([true], [true]));
25+
t.true(areArgumentArraysEqual([false], [false]));
26+
t.true(areArgumentArraysEqual([undefined], [undefined]));
27+
t.true(areArgumentArraysEqual([null], [null]));
28+
t.true(areArgumentArraysEqual([testObject], [testObject]));
29+
t.true(areArgumentArraysEqual([testArray], [testArray]));
30+
t.true(areArgumentArraysEqual([testFunc], [testFunc]));
31+
t.true(areArgumentArraysEqual([parent], [parent]));
32+
t.true(areArgumentArraysEqual([root], [root]));
2333

24-
t.false(areArgumentArraysEqual(['a'],['b']));
25-
t.false(areArgumentArraysEqual([1],[2]));
26-
t.false(areArgumentArraysEqual([true],[false]));
27-
t.false(areArgumentArraysEqual([undefined],[null]));
28-
t.false(areArgumentArraysEqual([testObject],[testArray]));
34+
t.false(areArgumentArraysEqual(['a'], ['b']));
35+
t.false(areArgumentArraysEqual([1], [2]));
36+
t.false(areArgumentArraysEqual([true], [false]));
37+
t.false(areArgumentArraysEqual([undefined], [null]));
38+
t.false(areArgumentArraysEqual([testObject], [testArray]));
2939

3040
// multi
31-
t.true(areArgumentArraysEqual([1,2,3], [1,2,3]));
41+
t.true(areArgumentArraysEqual([1, 2, 3], [1, 2, 3]));
3242

33-
t.false(areArgumentArraysEqual([1,2,3], [3,2,1]));
34-
t.false(areArgumentArraysEqual([1,2,3,4], [1,2,3]));
35-
t.false(areArgumentArraysEqual([1,2,3], [1,2,3,4]));
36-
})
43+
t.false(areArgumentArraysEqual([1, 2, 3], [3, 2, 1]));
44+
t.false(areArgumentArraysEqual([1, 2, 3, 4], [1, 2, 3]));
45+
t.false(areArgumentArraysEqual([1, 2, 3], [1, 2, 3, 4]));
46+
});
3747

3848
test('areArgumentArraysEqual should return valid result using Arg.all()', t => {
39-
t.true(areArgumentArraysEqual([Arg.all()],[]));
40-
t.true(areArgumentArraysEqual([Arg.all()],[0]));
41-
t.true(areArgumentArraysEqual([Arg.all()],[1]));
42-
t.true(areArgumentArraysEqual([Arg.all()],['string']));
43-
t.true(areArgumentArraysEqual([Arg.all()],[true]));
44-
t.true(areArgumentArraysEqual([Arg.all()],[false]));
45-
t.true(areArgumentArraysEqual([Arg.all()],[null]));
46-
t.true(areArgumentArraysEqual([Arg.all()],[undefined]));
47-
t.true(areArgumentArraysEqual([Arg.all()],[1,2]));
48-
t.true(areArgumentArraysEqual([Arg.all()],['string1', 'string2']));
49+
t.true(areArgumentArraysEqual([Arg.all()], []));
50+
t.true(areArgumentArraysEqual([Arg.all()], [0]));
51+
t.true(areArgumentArraysEqual([Arg.all()], [1]));
52+
t.true(areArgumentArraysEqual([Arg.all()], ['string']));
53+
t.true(areArgumentArraysEqual([Arg.all()], [true]));
54+
t.true(areArgumentArraysEqual([Arg.all()], [false]));
55+
t.true(areArgumentArraysEqual([Arg.all()], [null]));
56+
t.true(areArgumentArraysEqual([Arg.all()], [undefined]));
57+
t.true(areArgumentArraysEqual([Arg.all()], [1, 2]));
58+
t.true(areArgumentArraysEqual([Arg.all()], ['string1', 'string2']));
59+
t.true(areArgumentArraysEqual([Arg.all()], [parent, root]));
4960
})
5061

5162
test('areArgumentArraysEqual should return valid result using Arg.any()', t => {
@@ -60,6 +71,8 @@ test('areArgumentArraysEqual should return valid result using Arg.any()', t => {
6071
t.true(areArgumentArraysEqual([Arg.any()], [testArray]));
6172
t.true(areArgumentArraysEqual([Arg.any()], [testFunc]));
6273
t.true(areArgumentArraysEqual([Arg.any()], []));
74+
t.true(areArgumentArraysEqual([Arg.any()], [parent]));
75+
t.true(areArgumentArraysEqual([Arg.any()], [root]));
6376

6477
t.true(areArgumentArraysEqual([Arg.any('string')], ['foo']));
6578
t.true(areArgumentArraysEqual([Arg.any('number')], [1]));
@@ -74,6 +87,8 @@ test('areArgumentArraysEqual should return valid result using Arg.any()', t => {
7487
t.false(areArgumentArraysEqual([Arg.any('object')], ['foo']));
7588
t.false(areArgumentArraysEqual([Arg.any('array')], ['bar']));
7689
t.false(areArgumentArraysEqual([Arg.any('function')], ['foo']));
90+
t.true(areArgumentArraysEqual([Arg.any('object')], [parent]));
91+
t.true(areArgumentArraysEqual([Arg.any('object')], [root]));
7792
})
7893

7994
test('areArgumentArraysEqual should return valid result using Arg.is()', t => {

spec/didNotReceive.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import test from 'ava';
2+
import { Substitute, Arg } from '../src/index';
3+
import { SubstituteException } from '../src/SubstituteBase';
4+
5+
interface Calculator {
6+
add(a: number, b: number): number;
7+
subtract(a: number, b: number): number;
8+
divide(a: number, b: number): number;
9+
isEnabled: boolean;
10+
}
11+
12+
test('not calling a method correctly asserts the call count', t => {
13+
const calculator = Substitute.for<Calculator>();
14+
15+
calculator.didNotReceive().add(1, 1);
16+
t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException });
17+
t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException });
18+
});
19+
20+
test('not getting a property correctly asserts the call count', t => {
21+
const calculator = Substitute.for<Calculator>();
22+
23+
calculator.didNotReceive().isEnabled;
24+
t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException });
25+
t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException });
26+
});
27+
28+
test('not setting a property correctly asserts the call count', t => {
29+
const calculator = Substitute.for<Calculator>();
30+
31+
calculator.didNotReceive().isEnabled = true;
32+
t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException });
33+
t.throws(() => calculator.received().isEnabled = true, { instanceOf: SubstituteException });
34+
});
35+
36+
test('not calling a method with mock correctly asserts the call count', t => {
37+
const calculator = Substitute.for<Calculator>();
38+
calculator.add(1, 1).returns(2);
39+
40+
calculator.didNotReceive().add(1, 1);
41+
t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException });
42+
t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException });
43+
});
44+
45+
test('not getting a property with mock correctly asserts the call count', t => {
46+
const calculator = Substitute.for<Calculator>();
47+
calculator.isEnabled.returns(true);
48+
49+
calculator.didNotReceive().isEnabled;
50+
t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException });
51+
t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException });
52+
});

spec/index.test.ts

Lines changed: 1 addition & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import test from 'ava';
22

3-
import { Substitute, Arg } from '../src/index';
3+
import { Substitute, Arg } from '../src';
44
import { OmitProxyMethods, ObjectSubstitute } from '../src/Transformations';
55

66
class Dummy {
@@ -46,28 +46,6 @@ function initialize() {
4646
substitute = Substitute.for<Example>();
4747
};
4848

49-
test('can call received twice', t => {
50-
initialize();
51-
52-
substitute.c('blah', 'fuzz');
53-
const expectedMessage = 'Expected 1337 calls to the method c with arguments [\'foo\', \'bar\'], but received none of such calls.\nAll calls received to method c:\n-> call with arguments [\'blah\', \'fuzz\']'
54-
t.throws(() => substitute.received(1337).c('foo', 'bar'), { message: expectedMessage });
55-
56-
const expectedMessage2 = 'Expected 2117 calls to the method c with arguments [\'foo\', \'bar\'], but received none of such calls.\nAll calls received to method c:\n-> call with arguments [\'blah\', \'fuzz\']'
57-
t.throws(() => substitute.received(2117).c('foo', 'bar'), { message: expectedMessage2 });
58-
});
59-
60-
test('class string field get returns', t => {
61-
initialize();
62-
63-
substitute.a.returns("foo", "bar");
64-
65-
t.deepEqual(substitute.a, 'foo');
66-
t.deepEqual(substitute.a, 'bar');
67-
t.deepEqual(substitute.a, void 0);
68-
t.deepEqual(substitute.a, void 0);
69-
});
70-
7149
test('class with method called "received" can be used for call count verification when proxies are suspended', t => {
7250
initialize();
7351

@@ -86,27 +64,6 @@ test('class with method called "received" can be used for call count verificatio
8664
t.throws(() => substitute.received(2).received('foo'));
8765
});
8866

89-
test('partial mocks using function mimicks with all args', t => {
90-
initialize();
91-
92-
substitute.c(Arg.all()).mimicks(instance.c);
93-
94-
t.deepEqual(substitute.c('a', 'b'), 'hello a world (b)');
95-
});
96-
97-
test('class string field get received', t => {
98-
initialize();
99-
100-
void substitute.a;
101-
void substitute.a;
102-
void substitute.a;
103-
void substitute.a;
104-
105-
t.throws(() => substitute.received(3).a);
106-
t.notThrows(() => substitute.received().a);
107-
t.notThrows(() => substitute.received(4).a);
108-
});
109-
11067
test('class string field set received', t => {
11168
initialize();
11269

@@ -128,60 +85,6 @@ test('class string field set received', t => {
12885
t.throws(() => substitute.received(3).v = 'hello');
12986
});
13087

131-
test('class method returns with placeholder args', t => {
132-
initialize();
133-
134-
substitute.c(Arg.any(), "there").returns("blah", "haha");
135-
136-
t.is(substitute.c("hi", "there"), 'blah');
137-
t.is(substitute.c("his", "there"), 'haha');
138-
t.is<any>(substitute.c("his", "there"), void 0);
139-
t.is<any>(substitute.c("hi", "there"), void 0);
140-
});
141-
142-
test('partial mocks using function mimicks with specific args', t => {
143-
initialize();
144-
145-
substitute.c('a', 'b').mimicks(instance.c);
146-
147-
t.is(substitute.c('a', 'b'), 'hello a world (b)');
148-
});
149-
150-
test('class method returns with specific args', t => {
151-
initialize();
152-
153-
substitute.c("hi", "there").returns("blah", "haha");
154-
155-
t.is(substitute.c("hi", "there"), 'blah');
156-
t.is(substitute.c("hi", "there"), 'haha');
157-
t.is(substitute.c("hi", "there"), void 0);
158-
t.is(substitute.c("hi", "there"), void 0);
159-
});
160-
161-
test('returning other fake from promise works', async t => {
162-
initialize();
163-
164-
const otherSubstitute = Substitute.for<Dummy>();
165-
substitute.returnPromise().returns(Promise.resolve(otherSubstitute));
166-
t.is(otherSubstitute, await substitute.returnPromise());
167-
});
168-
169-
test('returning resolved promises works', async t => {
170-
initialize();
171-
172-
substitute.returnPromise().returns(Promise.resolve(1338));
173-
174-
t.is(1338, await substitute.returnPromise());
175-
});
176-
177-
test('resolving other fake works', async t => {
178-
initialize();
179-
180-
const otherSubstitute = Substitute.for<Dummy>();
181-
substitute.returnPromise().resolves(otherSubstitute);
182-
t.is(otherSubstitute, await substitute.returnPromise());
183-
});
184-
18588
test('resolving promises works', async t => {
18689
initialize();
18790

@@ -247,57 +150,3 @@ test('partial mocks using property instance mimicks', t => {
247150

248151
t.deepEqual(substitute.d, 1337);
249152
});
250-
251-
test('verifying with more arguments fails', t => {
252-
initialize()
253-
substitute.bar(1)
254-
substitute.received().bar(1)
255-
t.throws(() => substitute.received().bar(1, 2))
256-
})
257-
258-
test('verifying with less arguments fails', t => {
259-
initialize()
260-
substitute.bar(1, 2)
261-
substitute.received().bar(1, 2)
262-
t.throws(() => substitute.received().bar(1))
263-
})
264-
265-
test('return with more arguments is not matched fails', t => {
266-
initialize()
267-
substitute.bar(1, 2).returns(3)
268-
t.is(3, substitute.bar(1, 2))
269-
t.is('function', typeof (substitute.bar(1)))
270-
})
271-
272-
test('return with less arguments is not matched', t => {
273-
initialize()
274-
substitute.bar(1).returns(3)
275-
t.is(3, substitute.bar(1))
276-
t.is('function', typeof (substitute.bar(1, 2).toString))
277-
})
278-
279-
test('can stub multiple primitive return values', t => {
280-
initialize()
281-
substitute.bar(1).returns(2)
282-
substitute.bar(2).returns(3)
283-
t.is(2, substitute.bar(1))
284-
t.is(3, substitute.bar(2))
285-
})
286-
287-
test('can stub multiple Arg values', t => {
288-
initialize()
289-
substitute.bar(Arg.is(x => x % 2 === 0)).returns(1)
290-
substitute.bar(Arg.is(x => x % 2 !== 0)).returns(2)
291-
t.is(1, substitute.bar(4))
292-
t.is(2, substitute.bar(5))
293-
})
294-
295-
296-
test.skip('can stub primitive & Arg values', t => {
297-
initialize()
298-
substitute.bar(1).returns(2)
299-
substitute.bar(Arg.any()).returns(3) // throws 'substitute.bar(...).returns is not a function'
300-
t.is(5, substitute.bar(2))
301-
t.is(2, substitute.bar(1))
302-
t.is(3, substitute.bar(2))
303-
})

spec/issues/15.test.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)