DEV Community

Xuanzi
Xuanzi

Posted on • Edited on

Run a local mock server in your project

At first, i'm not a native english speaker, so forgive me for my poor english, but i still try to write the article as accurately as possible.

I'm the author of the fake data library suchjs, recently i add a new feature to the command line tool such-cli what is based on suchjs, that is, to run a local mock server by executing the command npx such serve.

We often encounter some projects with separated front-back ends. Most time, the front end engineers start the working when the backend's APIs are not ready yet, so we need mock the APIs with data formats what are agreed by both front-end and back-end engineer.

Some open source like YApi can build a web platform for doing this. You can did good managements by using it, but the whole process from deploying the platform to creating the mock APIs is a bit complicated. If you just need handle a few APIs and need more customization, the such-cli will provide another choice.

Now i will introduce how to use it to run a mock server in your local project.

The first step:

Install the such-cli package.

# npm
npm install --save-dev such-cli
# yarn
yarn add -D such-cli
# pnpm
pnpm add -D such-cli
Enter fullscreen mode Exit fullscreen mode

The second step:

Initialize the suchjs config.

npx such init
Enter fullscreen mode Exit fullscreen mode

You just need configure step by step according to the question prompts.

After that, you will get a directory structure like this(the default config):

|- such.config.js # the suchjs config file
|- suchas/    # the root directory of suchjs files
|---- data/ # save the data file such as dicts and json
|---- server/ # save the mock template file
Enter fullscreen mode Exit fullscreen mode

The third step:

Start the mock server.

npx such serve -p 8181 -w
Enter fullscreen mode Exit fullscreen mode

After that, a node server will running at your localhost: http://localhost:8181.

The -w option means --watch, will watch the config file such.config.js's change and restart the server with a hot reload.

Now the mock server is startup, but it can't accept any request yet. Suppose you have a request named http://localhost:8181/api/v1/user/list, and you need to return a json response like this:

{
  "errno": 0,
  "errmsg": "",
  "data": {
     "total": 1000,
     "users": [{
        id: 1,
        firstName: "abc",
        lastName: "def",
        fullName: "abc def",
        email: "xxx@gmail.com",
        mobile: "xxx"         
     },{
        "...": "more data"
     }]
  }
}
Enter fullscreen mode Exit fullscreen mode

Or an error occurred:

{
  "errno": 1,
  "errmsg": "some message"
}
Enter fullscreen mode Exit fullscreen mode

Now let's do some analysis:

  • The /api/v1 is a global prefix of our most requests.
  • The /api/v1/user/list is a get request and non restful.

Then let's do some configure for the such.config.js:

// such.config.js
module.exports = {
   // ...
   config: {
     server: {
        prefix: ["/api/v1", {
           // some APIs with pathname not begin with `/api/v1` 
           // it's similar to nestjs `setGlobalPrefix`
           exclude: []
        }],
        // use a dot '.' for joining the pathname segments 
        pathSegSplit: "."
     }
   }
};
Enter fullscreen mode Exit fullscreen mode

Since the request's pathname is /api/v1/user/list, we remove the global prefix /api/v1 from it, the remaining path becomes to user/list, so we join the two segments user and list of the path with the dot '.' (pathSegSplit), we get a file name without extension user.list.

At last, we know that the request is of json data type, so we choose the .json as the file's extension name. This can be configured in the such.config.js's extContentTypes field.

// such.config.js
module.exports = {
   server: {
      extContentTypes: {
         ".json": "application/json",
         ".js": ["text/javascript", "application/javascript"]
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

If the requested content-type matches the corresponding extension content-type list in the extContentTypes, the extension will be used for the file name at last, otherwise The extension list in the configuration extensions will be combined with the file name to form the final file path to be searched one by one.

// such.config.js
module.exports = {
   // ...
   extensions: [".json", ".js", ".txt"],
   server: {
      // ...
   }
}
Enter fullscreen mode Exit fullscreen mode

Back to the topic, we get the file name user.list.json at last. So we create it under the server directory.

cd ./suchas/server
touch user.list.json
Enter fullscreen mode Exit fullscreen mode

Then we edit the file user.list.json as a mock data template(the fake data rule is based on suchjs):

// suchas/server/user.list.json
{
  "errno:{1}": [0, 1],
  "errmsg:{1}": ["", ":string:{10,30}"],
  "data?": {
     "total": ":int:[1000,2000]",
     "users{3,10}": {
         "id": ":increment"
         "firstName": ":lowercase:{3,8}",
         "lastName": ":lowercase:{3,8}",
         "fullName": ":::`:ref:&./firstName` `:ref:&./lastName`",
         "email": ":email:#[domain='gmail.com']",
         "mobile": ":regexp:/(\\([0-9]{3}\\)|[0-9]{3}-)[0-9]{3}-[0-9]{4}/" 
     }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we open the url http://localhost:8181/api/v1/user/list in the browser, we will see the response json data at the page.

But at the moment, the json data format may not exactly what we wanted. We need do some customization to make the data more exactly.

Go on editing the such.config.js:

// such.config.js
module.exports = {
  server: {
     // ...
     buildConfig(pathname, ctx, config){
        if(pathname === "user/list"){
           const t = +new Date;
           if(t % 5 === 1){
              // random response an error
              return {
                 instance: {
                    keys: {
                      "/errno": {
                         index: 1
                      },
                      "/errmsg": {
                         index: 1
                      },
                      "/data": {
                         exists: false
                      }
                    } 
                 }
              };
           }
           const min = ctx.query('page') < 10 ? 10 : 3;
           return {
               timeout: [200, 500],
               instance: {
                  keys: {
                    "/errno": {
                       index: 0
                    },
                    "/errmsg": {
                       index: 0
                    },
                    "/data": {
                       exists: true,
                    },
                    "/data/users": {
                       min
                    }
                  } 
               }
           };
        }
     }
  }
};
Enter fullscreen mode Exit fullscreen mode

After saving the config, refresh the page, now the returned json data is closer to our needs at last.

At the end, we extract some common data types into the configuration so we can use them in all the mock data template files.

// such.config.js
module.exports = {
  types: {
     mobile$us: [
       "regexp", 
       "/(\\([0-9]{3}\\)|[0-9]{3}-)[0-9]{3}-[0-9]{4}/"
     ]
  }
};
Enter fullscreen mode Exit fullscreen mode
{
   "data?": {
      "users{3,10}": {
         "mobile": ":mobile$us"
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

Finally, the mock server worked fine, we just add more mock data template files for more APIs. Maybe you have a restful API, you just need create nested directories like the pathname segments and create files with the method name, such as get.json, post.json, put.json, more details can be seen in the github such-cli.

Thanks for taking the time to read this article. Hope it can help someone with mock needs.

Top comments (0)