2

テストが実施されていない typescript@2 プロジェクトを継承しました。

これは基本的に cli タスク ランナーであり、タスクはファイルを作成するために外部 API を複数回要求します。最初のフェイルセーフとして、受け入れテストをセットアップしたいと考えています。

したがって、外部 API への呼び出しをモックし、ローカル ファイルから応答を取得したいと考えています。どうすればそれを達成できますか?

この機能を提供しているように見える nock を調べましたが、どのように使用すればよいですか?

(私は最近、試練全体を経験したばかりなので、自分の質問に自分で答えるつもりなので、例を提供しません。)

4

1 に答える 1

4

executeTask オブジェクトがそのメソッドを実行するときに、外部 API へのすべての呼び出しが発生するように、アプリケーションをリファクタリングしました。このようなタスクはインターフェースを実装しますITask:

import {ReadStream} from 'fs';
export interface ITask {
    execute(): Promise<ReadStream>;
}

これにより、タスクをレコーダーまたは再生デコレーター内にラップすることができました。(またexecute、もうファイルを作成させませんが、ストリームの Promise を返します。通常のワークフローでは、そのストリームをファイル システムにダンプします (または、必要な場所にアップロードします)。

レコードデコレータ:

import {writeFile} from 'fs';
import {ITask} from './ITask';
import nock = require('nock');
import mkdirp = require('mkdirp');
import {ReadStream} from 'fs';

export class TaskMockRecorder implements ITask {
    constructor(private task: ITask, private pathToFile: string) {
    }

    public async execute(): Promise <ReadStream> {
        this.setupNock();
        const stream = await this.task.execute();
        this.writeRecordFile();

        return Promise.resolve(stream);
    }

    private writeRecordFile() {
        const nockCallObjects = nock.recorder.play();

        mkdirp(this.pathToFile, async() => {
            writeFile(`${this.pathToFile}`, JSON.stringify(nockCallObjects, null, 4));
        });
    }

    private setupNock() {
        nock.recorder.rec({
            dont_print: true,
            enable_reqheaders_recording: true,
            output_objects: true,
        });
    }
}

PlayBackDecorator

import {ITask} from './ITask';
import {ReadStream} from 'fs';
import {Partner} from '../Types';
import nock = require('nock');

export class TaskMockPlaybackDecorator implements ITask {
    constructor(private task: ITask, private pathToFile: string) {
    }

    public async execute(): Promise<ReadStream> {
        nock.load(this.pathToFile);
        nock.recorder.play();

        return this.task.execute();
    }
}

タスクの装飾

さらにカスタムタイプを導入しましたMockMode

export type MockeMode = 'recording'|'playback'|'none';

これを appRunner 関数に挿入できます。

export async function appRun(config: IConfig, mockMode: MockeMode): Promise<ReadStream> {
    let task: ITask;

    task = new MyTask(config);

    const pathToFile = `tapes/${config.taskName}/tape.json`;
    switch (mockMode) {
        case 'playback':
            console.warn('playback mode!');
            task = new TaskMockPlaybackDecorator(task, path);
            break;
        case 'recording':
            console.warn('recording mode!');
            task = new TaskMockRecorder(task, path);
            break;
        default:
            console.log('normal mode');
    }

    const csvStream = await task.execute();

    return Promise.resolve(csvStream);
}

受け入れテストの実装:

ここで、参照ファイルを追加し、再生実行から生成されたストリームと参照ファイルの両方を比較する mocha テストをセットアップする必要がありました。

import nock = require('nock');
import {appRun} from '../../src/core/task/taskRunner';
import {createReadStream} from 'fs';
import {brands} from '../../src/config/BrandConfig';
import isEqual = require('lodash/isEqual');
const streamEqual = require('stream-equal');

describe('myTask', () => {
    const myConfig = { // myConfig // }
    const referencePath = `references/${myConfig.taskName}.csv`;
    it(`generates csv that matches ${referencePath}`, async() => {
        nock.load(`tapes/${config}.taskName}/tape.json`);
        nock.recorder.play();

        return new Promise(async(resolve, reject) => {
            const actual = await appRun(myConfig, 'playback');
            const expected = createReadStream(referencePath);
            streamEqual(actual, expected, (err: any, isEqual: boolean) => {
                if (err) {
                    reject(err);
                }
                if (isEqual) {                          
                    resolve('equals');
                    return;
                }

                reject('not equals');               
            });
        });
    });
});

timeoutデフォルトは 2 秒で、これらの種類のテストは実行が遅くなる可能性があるため、録音された json リクエスト/レスポンスのサイズによっては、 を介して実行サイズを増やす必要がある場合があります。

mocha --recursive dist/tests -t 10000

このアプローチにより、テープを簡単に更新することも可能になります。mockMode引数として からパラメーターを渡すだけで、 tape.json.

欠点は、tape.jsonトラフィックの量によっては巨大になる可能性があることですが、コードベースに変更が加えられてもアプリケーションが同じように動作することを確認するための最初のステップとして、これは意図的なものでした。

于 2016-12-04T15:18:05.233 に答える