Как выполнить модульное тестирование метода AWS SDK, вызываемого в отдельном методе? - PullRequest
0 голосов
/ 21 января 2019

В настоящее время я пишу фрагмент кода, который просто загружает файл в корзину S3.Это безсерверный проект NodeJS, написанный на Typescript.Для тестирования я использую Mocha, Chai и пытаюсь использовать SinonJS.

У меня есть класс с методом, который загружает буфер в виде файла на S3:

import { S3 } from "aws-sdk"
import { S3UploadError } from "../errors/S3UploadError"

/**
 * This class provides a means of interacting with S3
 *
 * @export
 * @class AWSS3Manager
 */
export class AWSS3Manager {
    /**
     * Instance of S3
     *
     * @private
     * @type {S3}
     * @memberof AWSS3Manager
     */
    private s3: S3

    /**
     * Creates an instance of AWSS3Manager.
     *
     * @memberof AWSS3Manager
     */
    public constructor() {
        this.s3 = new S3()
    }

    /**
     * Upload a file to bucket on S3 by using a buffer
     *
     * @param {Buffer} body
     * @param {string} bucketName
     * @param {string} fileName
     * @returns {Promise<PromiseResult<S3.PutObjectOutput, S3UploadError>>}
     * @memberof AWSS3Manager
     */
    public async upload(body: Buffer, bucketName: string, fileName: string) {
        const params = {
            Body: body,
            Bucket: bucketName,
            Key: fileName,
        }

        try {
            return await this.s3.putObject(params).promise()
        } catch (err) {
            console.log(err)
            throw new S3UploadError()
        }
    }
}

Я даже не уверен, что это правильно, но яхочу проверить метод upload вышеприведенного класса.И, на мой взгляд, для этого мне нужно смоделировать ответ от S3.putObject, чтобы убедиться, что внешняя библиотека не вызывает помех.Однако, что бы я ни пытался, я не могу заставить его работать.

Я попытался заглушить метод объекта S3 put, но безрезультатно:

chai.should()
const assert = chai.assert
const expect = chai.expect
const s3manager = new AWSS3Manager()
let sandbox: sinon.SinonSandbox
let spy

describe("AWSS3Manager behaves as expected", () => {
    beforeEach(() => {
        sandbox = sinon.createSandbox()
        spy = sinon.spy()

    })
    afterEach(() => {
        // Restore the default sandbox here
        sandbox.restore()
    })

    it("Uploads a file correctly to S3", async () => {
        const putObjectStub = sinon.stub(S3.prototype, "putObject")
        putObjectStub.yields("ERROR", 'data')
        //const uploadStub = sandbox.stub(s3manager, "upload").resolves("Yup")
        //sandbox.stub(AWS, "S3").resolves('HEYY')
        const test = await s3manager.upload(new Buffer("ddds"), "TestBucket", "Test")
        assert(putObjectStub.called)
    })
})

Я попытался заглушить метод S3, а также метод загрузки самого себя и увидетьсколько звонков было, чтобы поставить объект, но я не могу заставить ничего работать.

Кто-нибудь может помочь?

1 Ответ

0 голосов
/ 20 марта 2019

Я столкнулся с подобной ситуацией, пытаясь заглушить вызов putObject на экземпляре S3, который я затем возвращал прикованным .promise().См. Ниже:

export class UploadService {
  s3: S3

  constructor() {
    this.s3 = new S3({ region: 'us-west-2' })
  }

  upload({ data, path }: { data: string, path: string }) {
    const uploadParams = {
      Body: data,
      Bucket: bucketName, // defined elsewhere
      Key: path
    }
    return this.s3.putObject(uploadParams).promise()
  }
}

Я копался в определениях aws-sdk и придумал эту тестовую настройку - мне это не нравится, потому что она как бы обнажает кишки SDK, которых у вас не должно бытьдумать, но он проходит компилятор машинописного текста и выполняет свою работу ?‍♂️

import { expect } from 'chai'
import * as sinon from 'sinon'
import { UploadService } from '../../src/services/upload_service'
import { Request, Service } from 'aws-sdk'

describe('UploadService', () => {
  const uploadService = new UploadService()
  let uploadStub: sinon.SinonStub

  describe('#upload', () => {
    beforeEach(() => {
      uploadStub = sinon
        .stub(uploadService.s3, 'putObject')
        .returns(new Request(new Service(), 'put'))
    })
    it('uploads the data to the specified path in S3', async () => {
      const data = '{"cool": "data"}'
      const path = 'my/cool/file/path'

      await uploadService.upload({ data, path })

      expect(uploadStub).to.have.been.calledOnceWith({ data, path })
    })
  })
})

Надеюсь, это поможет!

...