Sinon 假计时器在测试中多次调用仅触发一次
Sinon Fake Timer Call multiple Times In Test Only Firing Once
我有一个递归调用自身的函数,直到它调用的函数完成。
这是正在测试的函数(我已经修改它以便在 Whosebug 上 post 因为它是专有的。):
private async awaitQueryCompletion(queryId: string): Promise<void> {
setTimeout(async () => {
const output: ExecutionOutput =
await this.getQueryExecution({ QueryExecutionId: queryId }).promise();
let state: string | undefined;
if (ExecutionOutput.QueryExecution !== undefined && ExecutionOutput.QueryExecution.Status) {
state = ExecutionOutput.QueryExecution.Status.State;
}
if (state !== undefined && state === "RUNNING") {
await this.awaitQueryCompletion(queryId);
}
}, this.RETRY_INTERVAL);
}
这是我的测试:
设置:
beforeEach(() => {
sandbox = createSandbox();
getQueryExecutionStub = sandbox.stub(QueryClass, "getQueryExecution")
timer = sandbox.useFakeTimers({ shouldAdvanceTime: true});
});
it.only("Should call getQueryExecution twice with correct params", async () => {
const INTERVAL: number = 5010;
getQueryExecutionStub.onFirstCall()
.returns({
promise: async (): Promise<ExecutionOutput> => {
return Promise.resolve({
QueryExecution: {
Status: {
State: "RUNNING"
}
}
});
}
});
getQueryExecutionStub.onSecondCall()
.returns({promise: async (): Promise<ExecutionOutput> => {
return Promise.resolve({
QueryExecution: {
Status: {
State: "SUCCEEDED"
}
}
});
}
});
await selector.query(testInput);
timer.tick(INTERVAL);
timer.tick(INTERVAL);
expect(getQueryExecutionStub.calledTwice).to.equal(true);
});
});
我想要的是 getQueryExecutionStub 被调用两次,所以我正在模拟 setTimeout 函数并尝试按想法行事发生了两个超时周期。我有一次达到 运行 超时,但我不知道如何再次达到 运行。任何和所有帮助将不胜感激!我查看了两个 lolex 文档:(https://github.com/sinonjs/lolex) and sinon fake timers docs (https://sinonjs.org/releases/v8.0.4/fake-timers/).
所以我在稍微挖掘之后就能弄明白这一点。
private async awaitQueryCompletion(queryId: string, context: Context): Promise<void> {
return new Promise(async (resolve: Function, reject: Function): Promise<void> => {
// tslint:disable-next-line: no-inferred-empty-object-type
this.timeout(async () => {
try {
log.debug("Checking query completion");
const queryExecutionOutput: Athena.GetQueryExecutionOutput =
await this.athenaClient.getQueryExecution({ QueryExecutionId: queryId }).promise();
let state: string | undefined;
if (queryExecutionOutput.QueryExecution !== undefined
&& queryExecutionOutput.QueryExecution.Status !== undefined) {
state = queryExecutionOutput.QueryExecution.Status.State;
}
if (state !== undefined && state === "RUNNING") {
if (context.getRemainingTimeInMillis() > this.TIMEOUT_PADDING_MS) {
await this.awaitQueryCompletion(queryId, context);
resolve();
} else {
log.error(`Failure: Unable to complete query before lambda shut down...`);
reject();
}
} else if (state === "SUCCEEDED") {
resolve();
} else if (state === "FAILED") {
throw new Error(state);
} else {
log.error("Unable to determine the state of the query...");
reject();
}
} catch (e) {
log.error(`${JSON.stringify(e)}`);
return reject(e);
}
}, this.RETRY_INTERVAL_MS);
});
}
我需要的是将我的函数包装在一个承诺中,并且在每个 tick
解决之后,下一个 tick
的承诺可以触发。
我有一个递归调用自身的函数,直到它调用的函数完成。 这是正在测试的函数(我已经修改它以便在 Whosebug 上 post 因为它是专有的。):
private async awaitQueryCompletion(queryId: string): Promise<void> {
setTimeout(async () => {
const output: ExecutionOutput =
await this.getQueryExecution({ QueryExecutionId: queryId }).promise();
let state: string | undefined;
if (ExecutionOutput.QueryExecution !== undefined && ExecutionOutput.QueryExecution.Status) {
state = ExecutionOutput.QueryExecution.Status.State;
}
if (state !== undefined && state === "RUNNING") {
await this.awaitQueryCompletion(queryId);
}
}, this.RETRY_INTERVAL);
}
这是我的测试: 设置:
beforeEach(() => {
sandbox = createSandbox();
getQueryExecutionStub = sandbox.stub(QueryClass, "getQueryExecution")
timer = sandbox.useFakeTimers({ shouldAdvanceTime: true});
});
it.only("Should call getQueryExecution twice with correct params", async () => {
const INTERVAL: number = 5010;
getQueryExecutionStub.onFirstCall()
.returns({
promise: async (): Promise<ExecutionOutput> => {
return Promise.resolve({
QueryExecution: {
Status: {
State: "RUNNING"
}
}
});
}
});
getQueryExecutionStub.onSecondCall()
.returns({promise: async (): Promise<ExecutionOutput> => {
return Promise.resolve({
QueryExecution: {
Status: {
State: "SUCCEEDED"
}
}
});
}
});
await selector.query(testInput);
timer.tick(INTERVAL);
timer.tick(INTERVAL);
expect(getQueryExecutionStub.calledTwice).to.equal(true);
});
});
我想要的是 getQueryExecutionStub 被调用两次,所以我正在模拟 setTimeout 函数并尝试按想法行事发生了两个超时周期。我有一次达到 运行 超时,但我不知道如何再次达到 运行。任何和所有帮助将不胜感激!我查看了两个 lolex 文档:(https://github.com/sinonjs/lolex) and sinon fake timers docs (https://sinonjs.org/releases/v8.0.4/fake-timers/).
所以我在稍微挖掘之后就能弄明白这一点。
private async awaitQueryCompletion(queryId: string, context: Context): Promise<void> {
return new Promise(async (resolve: Function, reject: Function): Promise<void> => {
// tslint:disable-next-line: no-inferred-empty-object-type
this.timeout(async () => {
try {
log.debug("Checking query completion");
const queryExecutionOutput: Athena.GetQueryExecutionOutput =
await this.athenaClient.getQueryExecution({ QueryExecutionId: queryId }).promise();
let state: string | undefined;
if (queryExecutionOutput.QueryExecution !== undefined
&& queryExecutionOutput.QueryExecution.Status !== undefined) {
state = queryExecutionOutput.QueryExecution.Status.State;
}
if (state !== undefined && state === "RUNNING") {
if (context.getRemainingTimeInMillis() > this.TIMEOUT_PADDING_MS) {
await this.awaitQueryCompletion(queryId, context);
resolve();
} else {
log.error(`Failure: Unable to complete query before lambda shut down...`);
reject();
}
} else if (state === "SUCCEEDED") {
resolve();
} else if (state === "FAILED") {
throw new Error(state);
} else {
log.error("Unable to determine the state of the query...");
reject();
}
} catch (e) {
log.error(`${JSON.stringify(e)}`);
return reject(e);
}
}, this.RETRY_INTERVAL_MS);
});
}
我需要的是将我的函数包装在一个承诺中,并且在每个 tick
解决之后,下一个 tick
的承诺可以触发。