JSON API測試方法

JSON API Testing Methods | Master 7 Tools to Boost Debugging Efficiency by 10x!

2 AM, production environment crashes, API returns 500 error, backend says "it works on my machine"? Stop fishing in console.log! Professional API testing tools can help you find the root cause in 5 minutes, from Postman's GUI to Jest automation to CI/CD integration. This article teaches you 7 weapons, covering manual testing, automation, and performance testing, boosting your API debugging efficiency 10x and achieving 100% test coverage!


七大工具比較表格
七大工具比較表格

What is JSON API Testing? Why Is It So Important?

Core Goals of API Testing

API (Application Programming Interface) testing is the process of verifying whether backend services correctly return data. For JSON APIs, it mainly checks:

  1. Response Format: Is JSON syntax correct
  2. Data Structure: Field names, types, nesting levels
  3. Status Codes: 200 (success), 400 (bad request), 500 (server error)
  4. Performance: Is response time within acceptable range
  5. Edge Cases: Handling of extreme inputs (null values, huge numbers)

Why Can't We Just Rely on "Manual Testing"?

Pain Point 1: Repetitive Work
Manually testing 20 API endpoints every time code changes? Waste of time!

Pain Point 2: Easy to Miss
Manual testing can't achieve 100% coverage; edge cases are always missed.

Pain Point 3: No Regression Testing
Bug fixed last month reappears in this release? Because there's no automated testing!

Solution: Mixed Testing Strategy
- Manual Testing: Quick validation of new features (Postman, curl)
- Unit Testing: Test single API endpoints (Jest, Mocha)
- Integration Testing: Test complete user flows (Cypress, Playwright)
- Performance Testing: Check API load capacity (k6, Apache JMeter)

Image Description:
  slug: "api-testing-pyramid"
  Scene Description: "Testing pyramid diagram, from bottom to top: unit tests (widest bottom layer), integration tests (middle layer), end-to-end tests (narrowest top layer), each layer marked with test quantity ratio"
  Visual Focus: "Pyramid's three-layer structure, bottom unit tests account for most (70%), middle integration tests (20%), top E2E tests (10%)"
  Required Elements: "Triangular pyramid, three layers, percentage labels, test type names, arrow indicators"
  Prohibited Elements: "Abstract icons (like gears, light bulbs), cartoon characters, 3D models"
  Color Scheme: "White background, blue bottom layer (#2563eb), green middle layer (#10b981), orange top layer (#f97316), black text"
  Chinese Text Requirements: "Must include Traditional Chinese labels like '單元測試 70%', '整合測試 20%', '端到端測試 10%'"
  Atmosphere: "Professional technical diagram, clear and understandable"
  Composition: "Vertical pyramid centered, layers clearly distinct"
  Size: "1200x630px, 16:9 ratio"
  Photography Style: "Infographic style, clean and clear, well-layered"
  Detail Requirements: "Each layer must label test type and recommended ratio, arrows indicate relationship between test cost and speed"
  People Requirements: "No people needed"
  Quality Requirements: "High resolution (at least 72 DPI), text clearly readable, obvious color contrast"

Postman測試工作流程
Postman測試工作流程

Why Choose Postman?

Postman is the world's most popular API testing tool (over 20 million users), providing:
- ✅ Graphical interface, no code required
- ✅ Auto-saves request history
- ✅ Supports environment variables (dev/test/production switching)
- ✅ Built-in JSON formatting and validation
- ✅ Can export test collections to share with team

Basic Usage Flow

Step 1: Create Request

  1. Open Postman → Click New → Select HTTP Request
  2. Choose request method (GET, POST, PUT, DELETE)
  3. Enter API URL: https://api.example.com/users
  4. Click Send

Step 2: Check Response

Postman will display:
- Status: 200 OK (success)
- Time: 123ms (response time)
- Size: 2.5KB (data size)
- Body: JSON formatted response content

Step 3: Validate JSON Format

If response format has issues, recommend copying to JSON Parser to validate syntax:

{
  "status": "success",
  "data": {
    "users": [
      { "id": 1, "name": "John Doe" },
      { "id": 2, "name": "Jane Smith" }
    ]
  }
}

Advanced Feature: Environment Variables

Problem: Dev, test, and production API URLs differ; manually changing each time?

Solution: Use environment variables

// Set environment variables
{
  "dev": {
    "baseUrl": "http://localhost:3000",
    "apiKey": "dev-key-123"
  },
  "production": {
    "baseUrl": "https://api.example.com",
    "apiKey": "prod-key-456"
  }
}

// Use variables in requests
GET {{baseUrl}}/api/users
Authorization: Bearer {{apiKey}}

Advanced Feature: Automated Test Scripts

Postman supports writing test assertions in JavaScript:

// Tests tab
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

pm.test("Response is JSON", function () {
    pm.response.to.be.json;
});

pm.test("Has users array", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData.data.users).to.be.an('array');
});

pm.test("First user has id", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData.data.users[0].id).to.exist;
});

API測試最佳實踐
API測試最佳實踐

Tool 2: curl (Command Line Swiss Army Knife)

Why Use curl?

curl is a command-line tool, lightweight, fast, cross-platform, suitable for:
- Quick testing of single APIs
- Writing automation in Shell scripts
- Testing directly on servers (no GUI)

Basic Syntax

GET Request:

curl https://api.example.com/users

POST Request (JSON data):

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name":"John Doe","age":30}'

Request with Authentication:

curl https://api.example.com/users \
  -H "Authorization: Bearer YOUR_API_KEY"

Save Response to File:

curl https://api.example.com/users > response.json

Advanced Tip: Beautify JSON Output

Problem: curl returns JSON as one line, hard to read.

Solution 1: Use jq (JSON processing tool)

curl https://api.example.com/users | jq '.'

# Outputs formatted JSON:
{
  "status": "success",
  "data": {
    "users": [
      {
        "id": 1,
        "name": "John Doe"
      }
    ]
  }
}

Solution 2: Use Tool Master

# 1. curl fetch data and save
curl https://api.example.com/users > raw.json

# 2. Paste into Tool Master JSON Parser to validate and format
# https://tool-master.cc/tools/json-parser

Debugging Tip: Show Detailed Information

# Show HTTP Headers
curl -i https://api.example.com/users

# Show complete request/response process (for debugging)
curl -v https://api.example.com/users

# Only show HTTP status code
curl -o /dev/null -s -w "%{http_code}\n" https://api.example.com/users

Tool 3: JavaScript Fetch API (Native Frontend Method)

Basic Usage

// GET request
fetch('https://api.example.com/users')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error('Error:', error);
  });

// POST request
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John Doe',
    age: 30
  })
})
  .then(response => response.json())
  .then(data => console.log(data));
async function getUsers() {
  try {
    const response = await fetch('https://api.example.com/users');

    // Check HTTP status
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('API request failed:', error);
  }
}

getUsers();

Error Handling Best Practices

async function fetchWithValidation(url) {
  try {
    const response = await fetch(url);

    // 1. Check HTTP status
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    // 2. Check Content-Type
    const contentType = response.headers.get('content-type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new Error('Response is not JSON format');
    }

    // 3. Parse JSON
    const data = await response.json();

    // 4. Validate data structure (optional)
    if (!data.status || !data.data) {
      throw new Error('JSON structure does not match expected format');
    }

    return data;
  } catch (error) {
    console.error('❌ API Error:', error.message);
    throw error;
  }
}

// Usage
fetchWithValidation('https://api.example.com/users')
  .then(data => console.log('✅ Success:', data))
  .catch(error => console.error('❌ Failed:', error));


🎯 Integrating Tool Master into API Testing Workflow

Professional API testing requires multiple tools working together:

Step Tool Purpose
1. Send Request Postman / curl / fetch Call API
2. Validate Format JSON Parser Check syntax errors
3. Visualize Structure JSON Parser Tree Viewer to quickly understand nested data

💡 Real-World Workflow:
1. Postman sends request, discovers response format issue
2. Copy response to JSON Parser to validate
3. Use Tree Viewer to quickly locate error field
4. Report to backend: "data.users[0].profile.avatar field format error"

👉 Try JSON Parser Now | View Technical Implementation Documentation



Tool 4: Axios (Powerful HTTP Client)

Why Choose Axios?

Axios is more powerful than native Fetch API:
- ✅ Automatic JSON conversion (no manual response.json())
- ✅ Supports request/response interceptors
- ✅ Automatically handles CSRF tokens
- ✅ Better error handling

Installation and Basic Usage

npm install axios
import axios from 'axios';

// GET request
const response = await axios.get('https://api.example.com/users');
console.log(response.data);

// POST request
const response = await axios.post('https://api.example.com/users', {
  name: 'John Doe',
  age: 30
});

// PUT request
await axios.put('https://api.example.com/users/1', {
  name: 'John Doe (Updated)'
});

// DELETE request
await axios.delete('https://api.example.com/users/1');

Advanced Feature: Request Interceptors

Auto-add Authentication Token:

// Set interceptor
axios.interceptors.request.use(config => {
  // Auto-add Authorization Header
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// All subsequent requests will auto-include token
axios.get('/api/users');  // Automatically includes Authorization Header

Advanced Feature: Response Interceptors

Unified Error Handling:

axios.interceptors.response.use(
  response => response,  // Success - return directly
  error => {
    // Unified error handling
    if (error.response) {
      switch (error.response.status) {
        case 401:
          console.error('Unauthorized, please login again');
          // Redirect to login page
          window.location.href = '/login';
          break;
        case 404:
          console.error('API does not exist');
          break;
        case 500:
          console.error('Server error');
          break;
      }
    }
    return Promise.reject(error);
  }
);

Tool 5: Jest (Automated Unit Testing)

Why Need Automated Testing?

Pain Point: Manually testing 50 APIs every time code changes?

Solution: Write tests once, run automatically thereafter!

Installation and Setup

npm install --save-dev jest

package.json:

{
  "scripts": {
    "test": "jest"
  }
}

Testing API Endpoints

// api.test.js
const axios = require('axios');

describe('User API', () => {
  test('GET /users should return user list', async () => {
    const response = await axios.get('https://api.example.com/users');

    // Validate status code
    expect(response.status).toBe(200);

    // Validate data structure
    expect(response.data).toHaveProperty('status', 'success');
    expect(response.data.data.users).toBeInstanceOf(Array);

    // Validate first record
    const firstUser = response.data.data.users[0];
    expect(firstUser).toHaveProperty('id');
    expect(firstUser).toHaveProperty('name');
  });

  test('POST /users should create new user', async () => {
    const newUser = { name: 'Test User', age: 25 };
    const response = await axios.post('https://api.example.com/users', newUser);

    expect(response.status).toBe(201);
    expect(response.data.data.user.name).toBe('Test User');
  });

  test('GET /users/999 should return 404', async () => {
    try {
      await axios.get('https://api.example.com/users/999');
    } catch (error) {
      expect(error.response.status).toBe(404);
    }
  });
});

Testing JSON Schema

const Ajv = require('ajv');
const ajv = new Ajv();

const userSchema = {
  type: 'object',
  properties: {
    id: { type: 'number' },
    name: { type: 'string' },
    email: { type: 'string', format: 'email' }
  },
  required: ['id', 'name', 'email']
};

test('API response conforms to Schema', async () => {
  const response = await axios.get('https://api.example.com/users/1');
  const user = response.data.data.user;

  const validate = ajv.compile(userSchema);
  const valid = validate(user);

  expect(valid).toBe(true);
  if (!valid) {
    console.error(validate.errors);
  }
});

Tool 6: Cypress (End-to-End Integration Testing)

Why Choose Cypress?

Cypress is suitable for testing complete user flows (End-to-End):
- ✅ Simulates real user actions (click, input, submit forms)
- ✅ Auto-waits for API responses (no manual sleep)
- ✅ Visual testing process (recording, screenshots)

Testing API and UI Integration

// cypress/integration/user.spec.js
describe('User Management Flow', () => {
  it('should be able to add user and see in list', () => {
    // Intercept API requests
    cy.intercept('POST', '/api/users').as('createUser');
    cy.intercept('GET', '/api/users').as('getUsers');

    // Visit page
    cy.visit('/users');

    // Click add button
    cy.get('[data-test="add-user-btn"]').click();

    // Fill form
    cy.get('[data-test="name-input"]').type('John Doe');
    cy.get('[data-test="email-input"]').type('[email protected]');

    // Submit
    cy.get('[data-test="submit-btn"]').click();

    // Wait for API response
    cy.wait('@createUser').then((interception) => {
      // Validate request content
      expect(interception.request.body.name).to.equal('John Doe');

      // Validate response
      expect(interception.response.statusCode).to.equal(201);
    });

    // Validate UI update
    cy.wait('@getUsers');
    cy.contains('John Doe').should('be.visible');
  });
});

Tool 7: k6 (Performance and Load Testing)

Why Need Performance Testing?

Scenario: Double 11 sale, traffic surges 10x, can API handle it?

k6 can simulate thousands of concurrent users to test API load capacity.

Installation and Basic Usage

brew install k6  # macOS

load-test.js:

import http from 'k6/http';
import { check, sleep } from 'k6';

export let options = {
  stages: [
    { duration: '30s', target: 20 },   // Ramp up to 20 users in 30 seconds
    { duration: '1m', target: 100 },   // Ramp up to 100 users in 1 minute
    { duration: '30s', target: 0 },    // Ramp down to 0 in 30 seconds
  ],
};

export default function () {
  const response = http.get('https://api.example.com/users');

  // Validate response
  check(response, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
    'is JSON': (r) => r.headers['Content-Type'].includes('application/json'),
  });

  sleep(1);
}

Run Test:

k6 run load-test.js

Output Report:

✓ status is 200........................: 100.00%
✓ response time < 500ms................: 95.32%
✓ is JSON..............................: 100.00%

http_req_duration.............avg=234ms  min=102ms  max=987ms
http_reqs.....................total=5432
vus...........................min=1      max=100
Image Description:
  slug: "api-performance-test"
  Scene Description: "k6 performance test results dashboard showing real-time request count, response time curves, error rate, throughput and other key metrics"
  Visual Focus: "Response time curve (line chart), concurrent users growth curve, green success rate indicators"
  Required Elements: "Terminal window or dashboard interface, line charts, data metrics (RPS, latency, error rate), timeline"
  Prohibited Elements: "Abstract icons (like gears, light bulbs), cartoon characters, 3D models"
  Color Scheme: "Dark background (#1e1e1e), green success indicators (#10b981), yellow warnings (#f59e0b), red errors (#ef4444), white text"
  Chinese Text Requirements: "Must include Traditional Chinese labels like '回應時間', '並發用戶', '成功率'"
  Atmosphere: "Professional monitoring dashboard, real-time data presentation"
  Composition: "Dashboard layout, multiple charts and metrics side by side or stacked"
  Size: "1200x630px, 16:9 ratio"
  Photography Style: "Screenshot or dashboard composite, sharp and clear, data clearly readable"
  Detail Requirements: "At least 2 line charts (response time, concurrent users), 3-4 key number indicators"
  People Requirements: "No people needed"
  Quality Requirements: "High resolution (at least 72 DPI), text clearly readable, smooth curves"

CI/CD Integration: Automated Testing Workflow

GitHub Actions Example

.github/workflows/api-test.yml:

name: API Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm install

      - name: Run Jest tests
        run: npm test

      - name: Run Cypress tests
        run: npx cypress run

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: test-results
          path: test-results/

Test Coverage Report

npm install --save-dev jest @jest/globals

# Run tests and generate coverage report
npm test -- --coverage

Output:

File             | % Stmts | % Branch | % Funcs | % Lines |
-----------------|---------|----------|---------|---------|
api/users.js     |   95.23 |    88.88 |     100 |   94.73 |
api/products.js  |   87.50 |    75.00 |     100 |   87.50 |
-----------------|---------|----------|---------|---------|
All files        |   91.36 |    81.94 |     100 |   91.11 |

Real-World Application Scenarios

Scenario 1: Frontend Calling Third-Party API

Problem: Integrating Google Maps API, but unsure of response format.

Testing Process:

// 1. Postman quick test
GET https://maps.googleapis.com/maps/api/geocode/json?address=Taipei101

// 2. Copy response to JSON Parser to validate
// https://tool-master.cc/tools/json-parser

// 3. Write test
test('Google Maps API returns correct format', async () => {
  const response = await axios.get('https://maps.googleapis.com/maps/api/geocode/json', {
    params: { address: 'Taipei101' }
  });

  expect(response.data.status).toBe('OK');
  expect(response.data.results).toBeInstanceOf(Array);
  expect(response.data.results[0].geometry.location).toHaveProperty('lat');
  expect(response.data.results[0].geometry.location).toHaveProperty('lng');
});

Scenario 2: Backend API Development

Problem: Developing new RESTful API, need to ensure all edge cases are correctly handled.

Testing Strategy:

describe('Products API', () => {
  // Normal cases
  test('GET /products should return product list', async () => { ... });

  // Edge cases
  test('GET /products?page=-1 should return 400', async () => { ... });
  test('GET /products?limit=99999 should limit max value', async () => { ... });

  // Error handling
  test('POST /products missing required fields should return 400', async () => { ... });
  test('DELETE /products/999 non-existent ID should return 404', async () => { ... });

  // Performance test
  test('GET /products should respond within 500ms', async () => {
    const start = Date.now();
    await axios.get('/api/products');
    const duration = Date.now() - start;
    expect(duration).toBeLessThan(500);
  });
});

Scenario 3: API Regression Testing

Problem: After last release, a field disappeared, users complaining continuously.

Solution: Create Snapshot Test

test('API response structure should not change (Snapshot)', async () => {
  const response = await axios.get('/api/users/1');

  // First run creates snapshot
  // Subsequent runs compare; fails if structure changes
  expect(response.data).toMatchSnapshot();
});

Common Errors and Solutions

Error 1: CORS Error

Error Message:

Access to fetch at 'https://api.example.com' from origin 'http://localhost:3000'
has been blocked by CORS policy

Cause: Backend hasn't set CORS Headers.

Solution (Backend):

// Express.js
const cors = require('cors');
app.use(cors({
  origin: ['http://localhost:3000', 'https://your-domain.com']
}));

// Or manually set
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

Error 2: JSON Parse Failure

Error Message:

SyntaxError: Unexpected token < in JSON at position 0

Cause: API returned something other than JSON (possibly HTML error page).

Solution:

const response = await fetch('/api/users');

// Check Content-Type
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
  const text = await response.text();
  console.error('API returned non-JSON:', text);
  throw new Error('API returned incorrect format');
}

const data = await response.json();

Recommend checking response content with JSON Syntax Error Solutions first.

Error 3: Flaky Tests

Problem: Same test sometimes passes, sometimes fails.

Common Causes:
- Depends on external API (network instability)
- Doesn't clean up test data (previous test affects next)
- Time-related logic (timezone issues)

Solutions:

// Use Mock to avoid external API dependency
jest.mock('axios');
axios.get.mockResolvedValue({
  data: { status: 'success', users: [...] }
});

// Clean data before each test
beforeEach(async () => {
  await db.users.deleteMany({});
});

// Fix time to avoid timezone issues
jest.useFakeTimers().setSystemTime(new Date('2025-01-01'));

Conclusion: Building Complete API Testing Strategy

Testing Pyramid Best Practices:

  1. 70% Unit Tests (Jest)
  2. Fast, cheap, high coverage
  3. Test single API endpoints

  4. 20% Integration Tests (Cypress)

  5. Test complete user flows
  6. API + UI integration

  7. 10% End-to-End Tests + Performance Tests (k6)

  8. Test critical business flows
  9. Ensure system load capacity

Tool Selection Recommendations:

Scenario Recommended Tool Reason
Quick Manual Testing Postman Most intuitive GUI
Server-side Testing curl Lightweight, fast, scriptable
Frontend Integration Axios Feature-complete, good error handling
Automated Testing Jest Most complete ecosystem
E2E Testing Cypress Visual, easy debugging
Performance Testing k6 Lightweight, accurate

Want to learn more JSON processing techniques? We recommend reading Complete JSON Parser Guide, or check out Tool Master Developer Tools Category to explore more useful tools!


Reference Resources

Official Documentation:
- Postman Official Documentation
- Jest Official Documentation
- Cypress Official Documentation
- k6 Official Documentation

Recommended Tools:
- Tool Master JSON Parser - Validate API response format
- Postman - Most popular API testing tool

Further Reading:
- Complete JSON Parser Guide - 7 Practical Tips from Beginner to Expert
- JSON Schema Validation Practical Guide - Auto-validate API response format
- Complete JSON Syntax Error Solutions - Quick format issue fixes
- JSON Formatter Best Practices - Optimize API response format
- JSON Beautifier Usage Guide - Beautify API test results
- Complete Online JSON Validator Guide - 5 Steps to Quick Validation


Start Professional API Testing Now! Use Tool Master JSON Parser to validate API responses, 100% local processing protects data security.

👉 Start Using JSON Parser