Skip to content

Commit a7df279

Browse files
committed
Replace mockery to sinon library in mock-run which is used for Tasks Unit Tests
1 parent 44e727d commit a7df279

File tree

3 files changed

+190
-14
lines changed

3 files changed

+190
-14
lines changed

node/mock-run.ts

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
import ma = require('./mock-answer');
2-
import mockery = require('mockery');
1+
import { TaskLibAnswers } from './mock-answer';
2+
import { SinonSandbox, createSandbox } from 'sinon';
33
import im = require('./internal');
4+
import * as taskLib from './task';
45

56
export class TaskMockRunner {
67
constructor(taskPath: string) {
78
this._taskPath = taskPath;
9+
this._sandbox = createSandbox();
810
}
911

1012
_taskPath: string;
11-
_answers: ma.TaskLibAnswers | undefined;
13+
_answers: TaskLibAnswers | undefined;
1214
_exports: {[key: string]: any} = { };
1315
_moduleCount: number = 0;
16+
private _sandbox: SinonSandbox;
1417

1518
public setInput(name: string, val: string) {
1619
let key: string = im._getVariableKey(name);
@@ -32,10 +35,43 @@ export class TaskMockRunner {
3235
*
3336
* @param answers Answers to be returned when the task lib functions are called.
3437
*/
35-
public setAnswers(answers: ma.TaskLibAnswers) {
38+
public setAnswers(answers: TaskLibAnswers) {
3639
this._answers = answers;
3740
}
3841

42+
checkModuleName(modName: any): boolean {
43+
if (typeof modName !== 'string') {
44+
return false;
45+
}
46+
47+
if (modName.includes('.')) {
48+
console.log(`WARNING: ${modName} is a local module. Cannot require it from task-lib. Please pass an already imported module.`);
49+
return false;
50+
}
51+
52+
return true;
53+
}
54+
55+
56+
checkIsMockable(newModule, methodName, oldModule) {
57+
const method = newModule[methodName];
58+
59+
if (!newModule.hasOwnProperty(methodName) || typeof method === 'undefined') {
60+
return false;
61+
}
62+
63+
if (typeof method !== 'function') {
64+
console.log(`WARNING: ${methodName} of ${newModule} is not a function. There is no option to replace getter/setter in this implementation. You can consider changing it.`);
65+
return false;
66+
}
67+
68+
const descriptor = Object.getOwnPropertyDescriptor(oldModule, methodName);
69+
70+
return descriptor && descriptor.writable !== false;
71+
}
72+
73+
74+
3975
/**
4076
* Register a mock module. When require() is called for the module name,
4177
* the mock implementation will be returned instead.
@@ -44,9 +80,22 @@ export class TaskMockRunner {
4480
* @param val Mock implementation of the module.
4581
* @returns void
4682
*/
47-
public registerMock(modName: string, mod: any): void {
83+
public registerMock(modName: any, mod: any): void {
4884
this._moduleCount++;
49-
mockery.registerMock(modName, mod);
85+
let oldMod: object;
86+
87+
if (this.checkModuleName(modName)) {
88+
oldMod = require(modName);
89+
} else {
90+
oldMod = modName;
91+
}
92+
93+
for (let method in oldMod) {
94+
if (this.checkIsMockable(mod, method, oldMod)) {
95+
const replacement = mod[method] || oldMod[method];
96+
this._sandbox.replace(oldMod, method, replacement);
97+
}
98+
}
5099
}
51100

52101
/**
@@ -69,11 +118,6 @@ export class TaskMockRunner {
69118
* @returns void
70119
*/
71120
public run(noMockTask?: boolean): void {
72-
// determine whether to enable mockery
73-
if (!noMockTask || this._moduleCount) {
74-
mockery.enable({warnOnUnregistered: false});
75-
}
76-
77121
// answers and exports not compatible with "noMockTask" mode
78122
if (noMockTask) {
79123
if (this._answers || Object.keys(this._exports).length) {
@@ -92,10 +136,21 @@ export class TaskMockRunner {
92136
tlm[key] = this._exports[key];
93137
});
94138

95-
mockery.registerMock('azure-pipelines-task-lib/task', tlm);
139+
140+
var tlt = require('azure-pipelines-task-lib/task');
141+
for (let method in tlt) {
142+
if (tlm.hasOwnProperty(method)) {
143+
this._sandbox.replace(tlt, method, tlm[method]);
144+
}
145+
}
146+
96147
}
97148

98149
// run it
99150
require(this._taskPath);
100151
}
152+
153+
public restore() {
154+
this._sandbox.restore();
155+
}
101156
}

node/package-lock.json

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

node/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"q": "^1.5.1",
3333
"semver": "^5.1.0",
3434
"shelljs": "^0.8.5",
35+
"sinon": "^15.2.0",
3536
"sync-request": "6.1.0",
3637
"uuid": "^3.0.1"
3738
},

0 commit comments

Comments
 (0)