首页 > 解决方案 > 无法使用 jest 模拟 s3

问题描述

我想模拟 s3.listObjects.promise() 并返回一个模拟值。但是,我不能这样做。这是我的实际代码,然后是单元测试。

const AWS = require('aws-sdk');

exports.handler = async (event,context,callback) => {
    console.log(`event is ${JSON.stringify(event)}`);

    const Bucket = event.s3Usage.Bucket;
    const Prefix = event.s3Usage.Prefix || "";

    let s3BucketSize = 0;
    console.log(`Bucket name is ${Bucket} and Prefix is ${Prefix}`);
    
    const s3 = new AWS.S3();
    try {
        const data = await s3.listObjects({ Bucket, Prefix }).promise();
        console.log(`Data is ${JSON.stringify(data)}`);
        if (data["Contents"].length > 1) {
            s3BucketSize = data["Contents"].filter(x => x.Size > 0).map(x => x.Size).reduce((x, y) => x + y);
            console.log(`Size of the folder is ${s3BucketSize} bytes.`);
        } else {
            console.log(`Size of the folder is 0 bytes.`);
        }
    } catch (err) {
        console.error(`Error is ${JSON.stringify(err)}`);
        callback(err)
    }

    return s3BucketSize;
}

以下是我的单元测试: -

const handler = require("../index").handler;
const { S3 } = require('aws-sdk');

jest.mock('aws-sdk');

const mockOutput = {
    "IsTruncated": false,
    "Marker": "",
    "Contents": [
        {
            "Key": "GodIsGreat.PNG",
            "LastModified": "2021-05-04T14:32:59.000Z",
            "ETag": "\"b45d6e6a40ab1c9ebf541093fe8959e6\"",
            "Size": 100,
            "StorageClass": "STANDARD",
            "Owner": {
                "ID": "98062a6ccbfb88d9b333868c14d5379ec23dab90210de79b2bfbd801e948ae0c"
            }
        },
        {
            "Key": "test/",
            "LastModified": "2021-03-02T08:09:37.000Z",
            "ETag": "\"d41d8cd98f00b204\"",
            "Size": 50,
            "StorageClass": "STANDARD",
            "Owner": {
                "ID": "98062a6ccbfb88d9b3338"
            }
        }
    ],
    "Name": "xx",
    "Prefix": "",
    "MaxKeys": 1000,
    "CommonPrefixes": []
};

const s3ListObjectsPromise = jest.fn().mockReturnValue({
    promise: jest.fn().mockResolvedValue(mockOutput)
});

S3.mockImplementation(() => ({
    listObjects: s3ListObjectsPromise
}));


const event = {
    s3Usage: {
        "Bucket": "xxx",
        "Prefix": ""
    }
};

describe("When the handler is invoked with an event", () => {
    // afterEach(jest.clearAllMocks);
    test("the correct response is returned", async () => {
        const res = await handler(event);
        console.log(`res value is ${res}`);
    });
});

当我运行测试时,我看到对 S3 对象的实际调用正在发生。如何避免这种情况?谢谢。

标签: javascriptnode.jsamazon-web-servicesunit-testingjestjs

解决方案


如果两个文件都在同一个项目下,这将正常工作。它失败的原因是因为我的实际代码和我的测试代码位于不同的项目中,其中安装了不同的 aws-sdk。

在引擎盖下,它们应该在相同的 aws-sdk 和 jest 中工作。

谢谢


推荐阅读