Amplify-cli: mock rest api locally

Created on 11 Feb 2020  ·  34Comments  ·  Source: aws-amplify/amplify-cli

Is your feature request related to a problem? Please describe.
I want to be able to run both the frontend and backend locally, control with environment variables when to produce/consume mock data and have the urls map to the right environment. I don't use GraphQL!

Describe the solution you'd like
amplify serve and mock -> frontend on localhost:3000 with env variables of mock && backend on localhost:3001 with env variables of mock

Describe alternatives you've considered
writing my own bash script passing environment variables in to every backend function

feature-request mock

Most helpful comment

+1 for local mocking of API Gateway. I'm surprised this isn't supported yet by amplify mock. It would be nice to be able to run amplify mock and aws-exports.js which is consumed by our web app would automatically point to the localhost REST API rather than the cloud one.

I'm currently able to run the express server locally via amplify function invoke, but automatically changing aws-exports.js and hot reloading the express server on code change does not happen through this method.

All 34 comments

@alexladerman thanks for the feature request, would you elaborate in details on your requirements, how would you imagine the developer workflow?

+1 for local mocking of API Gateway. I'm surprised this isn't supported yet by amplify mock. It would be nice to be able to run amplify mock and aws-exports.js which is consumed by our web app would automatically point to the localhost REST API rather than the cloud one.

I'm currently able to run the express server locally via amplify function invoke, but automatically changing aws-exports.js and hot reloading the express server on code change does not happen through this method.

Add me to this list. Let's pass this bill to congress!

This would be really useful!

At the moment i'm using:
amplify function invoke restapiName
this works pretty well.
https://aws-amplify.github.io/docs/js/react#testing-serverless-functions

+1 on this one. Would be great to quickly run amplify mock api when you have a basic rest api with express. I don't have a GraphQL backend so mock doesn't work.

+1

we can no longer use amplify function invoke to do this, this feature would be really useful for those of us who aren't using GraphQL!

+1 need this functionality

+1 or any alternative?

Hey guys, an alternative is to cd into the src folder and run the command “node app.js” and using dotenv for local environments, this will host your function on localhost port 3000 and u can test with postman. You can also use nodemon for hot reload.

+1

+1

+1

hello, can we please add the old amplify function invoke flow back? this is definitely making definitely significantly more tedious as the mock functionality replaced something that was working with something that is broken...

I used @AbirAbbas method and it does work. (thank you) It would be VERY NICE if I could use amplify mock api <NAME>, have aws-exports.js generate my local environment for my clientside app, and fully test. I am also thinking this would allow for easier testing in a pipeline.

+1

+1

+1

+1

+1

+1

+1 We are also waiting for this

+1

in addition to @AbirAbbas workaround, for ease of development you can add a script to your main package.json file that runs the command "node app.js".
package.json:
"scripts": { "server_dev": "node amplify/backend/function/<function_name>/src/app.js" }

and then just run npm run server_dev

This works only if you use a pure node project. If you use layers for example, it's not work.

Up

+1

+1

+1

Is this why - when I submit a query to the mock api - I get:

{ errorMessage: 'Must provide Source. Received: undefined' } 

?

+1, since we are able to use sam local start-api to test the REST APIs locally, I think it is reasonable to assume that Amplify is able to provide something similar :)

I'll share my workaround for this issue, it will allow local testing for the REST API, I've not looked into a local GraphQL API.

I just run yarn start for the frontend and yarn mock for the backend. You can also pass in events, see below.

package.json (at project root level to save changing to the function directory each time)

"scripts": {
"start": "cross-env PORT=8000 react-app-rewired start",
"mock": "nodemon amplify/backend/function/[YOUR API NAME]/src/index.js",
"mock:event": "nodemon amplify/backend/function/[YOUR API NAME]/src/index.js ./events/event.json",
}

Backend index.js

const handler = async (event, context) => {
  const awsServerlessExpress = require('aws-serverless-express')
  const app = require('./app')
  const server = awsServerlessExpress.createServer(app)

  console.log(`EVENT: ${JSON.stringify(event, null, 2)}`)

  // Express app
  return awsServerlessExpress.proxy(server, event, context, 'PROMISE').promise
}

;(async function () {
  /**
   * Support running function locally
   * ---------------------------------
   * Run `yarn mock` from project root
   * Requires `.env` in project root with:
   * - ENV=
   * - REGION=
   * - AWS_ACCESS_KEY_ID=
   * - AWS_SECRET_ACCESS_KEY=
   * - MOCK=true
   */
  if (
    process.env.npm_package_scripts_mock &&
    process.env.npm_package_scripts_mock.includes('nodemon')
  ) {
    process.env.MOCK = true
    require('dotenv').config()

    // getting the event from passed args
    const event = process.argv[2] ? require(process.argv[2]) : ''
    if (!event)
      console.log(
        `No event - run 'yarn mock:event' etc...`
      )
    const res = await handler(event, {
      done: () => {}, // err, success
    })
    if (res) console.log({ statusCode: res.statusCode, body: res.body })
  }
})()

module.exports = {
  handler,
}

React frontend

import Amplify from 'aws-amplify'
import React from 'react'
import ReactDOM from 'react-dom'

import App from './app'
import awsconfig from './aws-exports'

if (process.env.NODE_ENV === 'development') {
  awsconfig.aws_cloud_logic_custom = awsconfig.aws_cloud_logic_custom.map(
    (config) => {
      if (config.name === '[YOUR API NAME]') {
        config.endpoint = `http://${window.location.hostname}:3000`
      }
      return config
    }
  )
}
Amplify.configure(awsconfig)

ReactDOM.render(<App />, document.getElementById('root'))

Note, I've taken this code from my app and stripped it down, might need adjusting to work.

+1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

amlcodes picture amlcodes  ·  3Comments

gabriel-wilkes picture gabriel-wilkes  ·  3Comments

davo301 picture davo301  ·  3Comments

mwarger picture mwarger  ·  3Comments

darrentarrant picture darrentarrant  ·  3Comments