user1584120
user1584120

Reputation: 1261

"docClient.scan(...).promise is not a function" error when mocking AWS promises

I am trying to change some code from a callback to a promise, adding the .promise to the aws call.

const AWS = require("aws-sdk")

const docClient = new AWS.DynamoDB.DocumentClient({
  apiVersion: "2012-08-10",
  region: process.env.AWS_REGION
})

class Stuff {
   getRawItems() {
     let params = {
        TableName : "TableName"
     }

     return docClient.scan(params).promise()
       .then(function(data) {
          return data.Items
       })
       .catch(function(err) {
         console.warn("Error with Dynamo request", err)
         throw err
       })
   }
}

I think that's correct but the test is having an issue. I get the error:

'TypeError: docClient.scan(...).promise is not a function'

I think it has something to do with the way the mocks are written:

const fakeDynamo = { scan: jest.fn() }

const realAWS = require("aws-sdk")
realAWS.DynamoDB.DocumentClient = jest.fn( () => fakeDynamo )
const Stuff = require("../src/stuff").Stuff

test("Test that the scan is performed and the data comes back", done => {
   fakeDynamo.scan.mockImplementation( () => Promise.resolve({Items:[1,2,3]}))
   const stuff = new Stuff()
   const defaultItems = 
   stuff.getRawItems(lat, lon)
   defaultItems.then ( (data) => {
      expect(fakeDynamo.scan).toHaveBeenCalledTimes(1)
      expect(data.length).toEqual(3)
      done()
 })
})

Upvotes: 2

Views: 3462

Answers (3)

user3559247
user3559247

Reputation: 1228

I ran into this problem and found simplest solution to be get the mock to send a callback that gets treated as a promise.

fakePromise.promise.mockImplementation((params, callback) => callback(null, {Items:[1,2,3]}))

Upvotes: 0

user1584120
user1584120

Reputation: 1261

The mocks were the issue, here is the sample code for this:

const fakePromise = {
   promise : jest.fn()
}
const fakeDynamo = { scan: () => {
   return fakePromise
}}

const realAWS = require("aws-sdk")
realAWS.DynamoDB.DocumentClient = jest.fn( () => fakeDynamo )
const Stuff = require("../src/stuff").Stuff

test("Test that the scan is performed and the data comes back", done => {
  fakePromise.promise.mockImplementation(() => Promise.resolve({Items:[1,2,3]}))
  const stuff = new Stuff()
  const defaultItems = stuff.getRawItems(lat, lon)
  defaultItems.then ( (data) => {
     expect(fakePromise.promise).toHaveBeenCalledTimes(1)
     expect(data.length).toEqual(3)
     done()
  })
})

Upvotes: 4

Dennie de Lange
Dennie de Lange

Reputation: 2934

Maybe read up on Promises, I think

 return docClient.scan(params).promise()
   .then(function(data) {
      return data.Items
   })
   .catch(function(err) {
     console.warn("Error with Dynamo request", err)
     throw err
   })

Should be:

 return docClient.scan(params)
   .then(function(data) {
      return data.Items
   })
   .catch(function(err) {
     console.warn("Error with Dynamo request", err)
     throw err
   })

The parser is telling you: there's no promise function on the result of the scan function.

Upvotes: -1

Related Questions