🏠 ホーム ニュース 📖 解説記事 📚 トピック解説 🏷️ タグ一覧 ℹ️ About
🔍 記事を検索
カテゴリ
📡 RSSフィード
Follow
X (Twitter) 🧵 Threads
Quick Links
ニュース一覧 🏷️タグから探す
🧠Claude 🤖Agent 💬LLM 🔌MCP 🛠️Tool
Subscribe
📡 RSSフィード
ホーム tool 2026.04.05

Vercel Emulate:LocalStack代替の軽量マルチサービスエミュレーターでAWS/外部APIテストを自動化

vercel-labs/emulate
🧪
Vercel Emulate:LocalStack代替の軽量マルチサービスエミュレーターでAWS/外部APIテストを自動化 - AIツール日本語解説 | AI Heartland
// なぜ使えるか
AIモデルの動作確認は従来、手動テストや限定的なユニットテストに頼っていた。Emulateはモデルの出力を本番に近い環境で自動テストし、デプロイ前のリスク低減と信頼性向上を実現する。

概要

EmulateはVercel Labsが開発したサービスエミュレーター。Vercel、GitHub、Google、Slack、Apple、Microsoft、AWSなどの外部サービスをローカル環境で再現し、CI/CDパイプラインやネットワークが制限された環境でのテストを可能にする。本番環境に近い条件でのテスト実行により、デプロイ前のバグ検出と問題解決を加速させる仕組み。

主な機能

クイックスタート

インストール

Emulateはnpxで直接実行するか、プログラマティック利用時はnpmパッケージとして導入。

npx emulate

またはプログラマティックAPI使用時:

npm install emulate

基本的な実行方法

デフォルト設定で全サービスを起動:

npx emulate

起動時に以下のポートでサービスが利用可能になる:

CLIオプション

特定のサービスのみを起動する場合:

emulate --service vercel,github

カスタムポート指定:

emulate --port 3000

設定ファイルを使用:

emulate --seed config.yaml

設定ファイルの生成:

emulate init

特定サービスの設定生成:

emulate init --service vercel

利用可能なサービス一覧:

emulate list

CLIオプション一覧

フラグ デフォルト 説明
-p, --port 4000 基本ポート(サービスごとに自動加算)
-s, --service all カンマ区切りで指定するサービス
--seed auto-detect 設定ファイルパス(YAML/JSON)

ポートは環境変数 EMULATE_PORT または PORT でも設定可能。

プログラマティックAPI

基本的な使用方法

import { createEmulator } from 'emulate'

const github = await createEmulator({ service: 'github', port: 4001 })
const vercel = await createEmulator({ service: 'vercel', port: 4002 })

github.url   // 'http://localhost:4001'
vercel.url   // 'http://localhost:4002'

await github.close()
await vercel.close()

Vitest / Jest統合

// vitest.setup.ts
import { createEmulator, type Emulator } from 'emulate'

let github: Emulator
let vercel: Emulator

beforeAll(async () => {
  ;[github, vercel] = await Promise.all([
    createEmulator({ service: 'github', port: 4001 }),
    createEmulator({ service: 'vercel', port: 4002 })
  ])
})

afterAll(async () => {
  await Promise.all([github.close(), vercel.close()])
})

AWSサービス(SQS・S3)のエミュレーション

EmulateはAWSをローカルポート(デフォルト4006)でエミュレートする。AWS SDKの endpoint オプションにエミュレーターURLを指定するだけで、本番のIAM認証なしにS3やSQSのAPIを呼び出せる。

AWSエミュレーター単体起動

emulate --service aws
# → AWS on http://localhost:4006

SQSでキューメッセージの送受信をテスト

import { createEmulator } from 'emulate'
import { SQSClient, SendMessageCommand, ReceiveMessageCommand } from '@aws-sdk/client-sqs'

const aws = await createEmulator({ service: 'aws', port: 4006 })

const sqs = new SQSClient({
  region: 'us-east-1',
  endpoint: aws.url,
  credentials: { accessKeyId: 'test', secretAccessKey: 'test' }
})

const queueUrl = `${aws.url}/000000000000/test-queue`

// メッセージ送信
await sqs.send(new SendMessageCommand({
  QueueUrl: queueUrl,
  MessageBody: JSON.stringify({ event: 'user.created', userId: '123' })
}))

// メッセージ受信
const { Messages } = await sqs.send(new ReceiveMessageCommand({
  QueueUrl: queueUrl,
  MaxNumberOfMessages: 10
}))
console.log(Messages)

await aws.close()

S3でファイルのアップロード・取得をテスト

import { createEmulator } from 'emulate'
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'

const aws = await createEmulator({ service: 'aws', port: 4006 })

const s3 = new S3Client({
  region: 'us-east-1',
  endpoint: aws.url,
  forcePathStyle: true, // ローカルエミュレーターでは必須
  credentials: { accessKeyId: 'test', secretAccessKey: 'test' }
})

// ファイルアップロード
await s3.send(new PutObjectCommand({
  Bucket: 'test-bucket',
  Key: 'uploads/report.json',
  Body: JSON.stringify({ result: 'ok' }),
  ContentType: 'application/json'
}))

// ファイル取得
const { Body } = await s3.send(new GetObjectCommand({
  Bucket: 'test-bucket',
  Key: 'uploads/report.json'
}))
const text = await Body?.transformToString()
console.log(text) // '{"result":"ok"}'

await aws.close()

Vitestでの統合テスト例:

// s3.test.ts
import { createEmulator, type Emulator } from 'emulate'
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'

let aws: Emulator
let s3: S3Client

beforeAll(async () => {
  aws = await createEmulator({ service: 'aws', port: 4006 })
  s3 = new S3Client({
    region: 'us-east-1',
    endpoint: aws.url,
    forcePathStyle: true,
    credentials: { accessKeyId: 'test', secretAccessKey: 'test' }
  })
})

afterAll(() => aws.close())

test('S3にファイルをアップロードして取得できる', async () => {
  await s3.send(new PutObjectCommand({
    Bucket: 'test-bucket',
    Key: 'test.txt',
    Body: 'hello world'
  }))

  const { Body } = await s3.send(new GetObjectCommand({
    Bucket: 'test-bucket',
    Key: 'test.txt'
  }))

  expect(await Body?.transformToString()).toBe('hello world')
})

SlackエミュレーションでWebhookとAPIをテストする

EmulateはSlack APIをローカルポート(デフォルト4003)でエミュレートする。@slack/web-api@slack/webhook SDKの接続先URLを差し替えるだけで、Incoming Webhook・Bolt・slash commandのテストがネットワーク不要で実行可能。

Slack Web APIでメッセージ送信をテスト

emulate --service slack
# → Slack on http://localhost:4003
import { createEmulator } from 'emulate'
import { WebClient } from '@slack/web-api'

const slack = await createEmulator({ service: 'slack', port: 4003 })

// slackApiUrl にエミュレーターURLを指定
const client = new WebClient('xoxb-test-token', {
  slackApiUrl: `${slack.url}/api/`
})

const result = await client.chat.postMessage({
  channel: '#general',
  text: 'デプロイ完了! :rocket:',
  blocks: [
    {
      type: 'section',
      text: { type: 'mrkdwn', text: '*デプロイ完了*\n本番環境へのデプロイが成功しました。' }
    }
  ]
})

console.log('Message sent, ts:', result.ts)
await slack.close()

Incoming Webhookのテスト

import { createEmulator } from 'emulate'
import { IncomingWebhook } from '@slack/webhook'

const slack = await createEmulator({ service: 'slack', port: 4003 })

// WebhookのURLをエミュレーターに向ける
const webhook = new IncomingWebhook(
  `${slack.url}/services/T00000000/B00000000/XXXXXXXXXX`
)

await webhook.send({
  text: 'CI/CDパイプラインが完了しました',
  attachments: [
    {
      color: 'good',
      fields: [
        { title: 'ブランチ', value: 'main', short: true },
        { title: 'ステータス', value: '成功', short: true }
      ]
    }
  ]
})

await slack.close()

slash commandレスポンスのテスト

import { createEmulator, type Emulator } from 'emulate'

let slackEmulator: Emulator

beforeAll(async () => {
  slackEmulator = await createEmulator({ service: 'slack', port: 4003 })
})

afterAll(() => slackEmulator.close())

test('slash commandに正しく応答する', async () => {
  // エミュレーターにslash commandリクエストを直接送信
  const response = await fetch(`${slackEmulator.url}/commands`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      command: '/deploy',
      text: 'production',
      user_id: 'U123456',
      channel_id: 'C123456'
    })
  })
  expect(response.ok).toBe(true)
})

AWSとSlackを組み合わせた統合テスト

SQSメッセージをトリガーにSlackへ通知するフローなど、複数サービスをまたぐ処理もEmulateで一括テストできる。

sequenceDiagram participant Test as テストコード participant AWS as AWS Emulator
:4006 participant App as アプリケーション participant Slack as Slack Emulator
:4003 Test->>AWS: SQSメッセージ送信
(order.completed) AWS-->>App: メッセージ配信 App->>App: イベント処理 App->>Slack: chat.postMessage
(注文完了通知) Slack-->>Test: レスポンス確認 Test->>Test: アサーション
import { createEmulator, type Emulator } from 'emulate'
import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs'
import { WebClient } from '@slack/web-api'

let aws: Emulator
let slack: Emulator

beforeAll(async () => {
  ;[aws, slack] = await Promise.all([
    createEmulator({ service: 'aws', port: 4006 }),
    createEmulator({ service: 'slack', port: 4003 })
  ])
})

afterAll(async () => {
  await Promise.all([aws.close(), slack.close()])
})

test('SQSメッセージ受信後にSlack通知を送る', async () => {
  const sqs = new SQSClient({
    region: 'us-east-1',
    endpoint: aws.url,
    credentials: { accessKeyId: 'test', secretAccessKey: 'test' }
  })
  const slackClient = new WebClient('xoxb-test-token', {
    slackApiUrl: `${slack.url}/api/`
  })

  // SQSにイベントを投入
  await sqs.send(new SendMessageCommand({
    QueueUrl: `${aws.url}/000000000000/events`,
    MessageBody: JSON.stringify({ type: 'order.completed', orderId: '456' })
  }))

  // Slack通知関数を呼び出してテスト
  const result = await slackClient.chat.postMessage({
    channel: '#orders',
    text: '注文 #456 が完了しました'
  })

  expect(result.ok).toBe(true)
})

エミュレーター対応サービス比較

サービス ポート 主なエミュレート対象 代表的なSDK
AWS 4006 SQS、S3、DynamoDB等 @aws-sdk/client-sqs, @aws-sdk/client-s3
Slack 4003 Web API、Webhook、Events API @slack/web-api, @slack/webhook
GitHub 4001 REST API、Webhooks @octokit/rest
Vercel 4000 Deployments API @vercel/client
Google 4002 OAuth、Sheets、Drive等 googleapis

ユースケース

ローカル開発での外部API呼び出しのテスト

GitHub APIやVercel APIを呼び出すアプリケーションの開発時、ローカルエミュレーターを使用してネットワーク接続なしでテスト実行が可能。

CI/CDパイプラインでのネットワーク分離環境対応

CI環境がネットワークアクセスを制限している場合、Emulateでサービスをローカルエミュレートしてテストスイートを実行。

複数サービス統合のテスト

複数の外部サービス連携を扱うアプリケーションで、それぞれのサービスを同時にエミュレートして統合テストを実施。

アーキテクチャ

Emulateは各サービスをローカルポート上で独立したプロセスとして実行。アプリケーションはローカルホストの指定ポートにリクエストを送信することで、本番の外部サービスと同じインターフェースで通信可能。

graph TD App["アプリケーション"] App --> V["Vercel Emulator
:4000"] App --> G["GitHub Emulator
:4001"] App --> Go["Google Emulator
:4002"] App --> S["Slack Emulator
:4003"] App --> A["AWS Emulator
:4006"] V --> Impl["ステートフルなAPI実装
(Emulate コア)"] G --> Impl Go --> Impl S --> Impl A --> Impl

設定方法

YAML形式の設定例:

services:
  - name: vercel
    port: 4000
  - name: github
    port: 4001

JSON形式の設定例:

{
  "services": [
    {"name": "vercel", "port": 4000},
    {"name": "github", "port": 4001}
  ]
}

利点と注意点

Emulateは本番環境に近いAPI動作を提供するため、外部サービスの実装詳細をテストできる。一方、サービスの仕様変更時にはエミュレーターも同期更新が必要となる。また、全機能がエミュレートされているかは各サービスのドキュメントで確認が必要。

まとめ

EmulateはCI/CDパイプラインやローカル開発環境で外部サービスの呼び出しをテストする際に有用なツール。ネットワークが制限された環境での開発や、複数サービス統合の検証が必要なプロジェクトに適している。設定ファイルなしでもデフォルト設定で即座に主要サービスをエミュレート可能であり、段階的な導入が容易。

LocalStackとの違い:どちらを選ぶべきか

LocalStackはAWSサービスのローカルエミュレーターとして長年の実績を持つOSSで、80以上のAWSサービスに対応する。一方、Vercel Emulateは「AWS専用」ではなく、Vercel・GitHub・Slack・Google・MicrosoftなどマルチクラウドをDocker不要で即起動できる点が特徴だ。LocalStack代替として検討する際の比較ポイントをまとめる。

Vercel Emulate vs LocalStack 比較表

項目 Vercel Emulate LocalStack
セットアップ npx emulate で即起動(設定不要) Docker + compose設定が必要
対応サービス数 AWS含む主要7サービス(Vercel/GitHub/Google/Slack/Apple/Microsoft/AWS) AWS 80+サービス(S3/SQS/Lambda/DynamoDB/RDS等)
Docker依存 なし(Node.jsのみ) 必須(Docker Desktopが必要)
メモリ使用量 軽量(数十MB程度) 重量(数百MB〜1GB以上)
ユースケース 軽量テスト・CI環境・マルチサービス統合 本格AWSインフラテスト・IaCの検証
料金 OSS(完全無料) OSS無料 + LocalStack Pro(有料プランあり)
CI/CD統合 設定ゼロで動作・GitHub Actions対応 Docker-in-Dockerの設定が必要なケースあり
AWSカバレッジ 基本的なSQS/S3/DynamoDB相当 Lambda・ECS・RDS等の高度なサービスも対応
graph LR A["何をテストしたいか?"] A -->|"AWSのみ
本格インフラ"| B["LocalStack
(Lambda/RDS/ECS等が必要)"] A -->|"AWS + GitHub/Slack等
マルチサービス"| C["Vercel Emulate
(軽量・Docker不要)"] B --> D["LocalStack Pro検討
(高度なAWSサービス)"] C --> E["npx emulateで即スタート"]

LocalStackから乗り換えるべきケース

以下の条件に当てはまる場合、Vercel Emulateへの移行がLocalStack代替として有効な選択肢になる。

Vercel Emulateを選ぶべき状況:

# LocalStack(Docker必須)
docker run --rm -p 4566:4566 localstack/localstack

# Vercel Emulate(Docker不要・即起動)
npx emulate --service aws

LocalStackのままでいいケース

LocalStack代替を検討しても、以下のケースではLocalStackの継続利用が適切だ。

LocalStackを維持すべき状況:

LocalStack比較まとめ:EmulateはAWSに特化した深いエミュレーションより「素早くマルチサービスをモックしてCI/CDを回したい」ニーズにフィットする。LocalStack代替を探しているなら、まずユースケースの範囲を確認してから選択するのが賢明だ。

参照ソース

よくある質問
CI/CDパイプラインでEmulateを使用する際の利点は何ですか?
ネットワークアクセスが制限されたCI環境において、Emulateでサービスをローカルエミュレートしてテストスイートを実行できます。本番環境に近い条件でのテスト実行により、デプロイ前のバグ検出と問題解決が可能になります。
広告
🔌
MCP対応ツール特集
Claude Codeと連携できるMCPサーバーの日本語解説まとめ
GitHub で見る X 🧵 Threads Facebook LINE B! はてブ
🔔 AI速報、毎日Xで配信中
Claude Code・MCP・AIエージェントの最新ニュースをいち早くお届け
@peaks2314 をフォロー
記事の信頼性について
AI Heartland エディトリアルポリシーに基づき作成
複数ソース照合
公式情報・報道等を突き合わせて確認
ファクトチェック済
ソースURLの内容を検証
参照ソース明記
記事末尾に引用元を掲載
Next Read →
🤖 AIコーディングツールは内部でどう動くのか:Claude Codeのアーキテクチャを初心者向けに解説
関連記事
📨 Postiz:Buffer代替AIソーシャルメディア自動投稿ツール、19媒体をセルフホストで一括管理
PostizはBufferやHypefuryの完全OSS代替。Instagram・TikTok・X・LinkedIn等19媒体に対応し、AI投稿生成・チーム管理・n8n連携をDockerでセルフホスト運用できる。AGPLライセンス、スター27,000超。
2026.04.05
🎬 1本16円でYouTubeショート動画を全自動生成するOSS「YouTube Shorts Pipeline」の全貌
1本16円でYouTubeショート動画を全自動生成するOSSが登場。Claude+Gemini+ElevenLabs構成でリサーチから投稿まで完全自動。月1,000本でも16,000円。導入手順とアーキテクチャを解説
2026.04.02
🛠️ awesome-claude-skills:Claudeの能力拡張スキルをキュレーションするOSSリポジトリ
Anthropic製AI「Claude」向けのスキル・統合機能を集約したキュレーションリポジトリ。49,928スターを獲得。開発者がClaudeの機能拡張方法を一元検索可能にしており、エージェント開発を加速させる
2026.04.01
⚙️ Prefect:データパイプラインのワークフロー管理とスケジューリングプラットフォーム
21,997スター獲得のPrefectは、複雑なデータワークフロー構築・監視・スケジューリングを統合管理する。Pythonベースのオーケストレーション機能で、ETL・機械学習パイプラインの信頼性向上を実現。公式ドキュメントとコミュニティサポートで導入・運用が容易。
2026.03.31
Popular
#1 POPULAR
🔓 Claude Codeのソースコード流出、npmソースマップに51万行が丸見えだった件
Anthropic Claude Codeのnpmパッケージにソースマップが含まれ、1,902ファイル・51万行超のTypeScriptソースが公開状態に。未公開プロジェクト「KAIROS」や107個のフィーチャーフラグなど、内部コードの全貌を解説する。
#2 POPULAR
🚨 【速報】JavaScript主流ライブラリAxios、NPM供給チェーン攻撃でRAT配布
JavaScriptの週間1億DL HTTPクライアント「Axios」がNPM供給チェーン攻撃の被害に。[email protected]と0.30.4に悪意あるパッケージplain-crypto-jsが注入され、クロスプラットフォーム対応RATが配布。証拠自動削除機能を備えた高度な攻撃。
#3 POPULAR
⚠️ Anthropic、Claude Codeで予想外の高速クォータ枯渇認める。キャッシュバグで料金10〜20倍
Claude Codeでプロンプトキャッシュを破壊する2つのバグが発見され、API利用料が10〜20倍に跳ね上がる問題が発生。Anthropicは「チームの最優先事項」と認める。Pro/Maxユーザーから月間の大半で使用不可との報告多数。
#4 POPULAR
🔍 Claude Codeセキュリティ事件を切り分ける:ソース漏洩とaxios攻撃の違いと対処法
3月31日にClaude Codeで起きたソース漏洩とaxiosマルウェア。感染チェックコマンド・対策コードを交えて、2つの別事件の実態と具体的な対応手順を解説。
#5 POPULAR
🚀 ソフトウェア開発者ではない人が400ドルから年7M達成。AI時代の先発者優位性
AI技術を活用して短期間で大規模な収益を生み出した事例から、開発経験がなくても可能な起業の実態と、AI知識の先発者優位性について解説する。
← Awesome Seedance 2 Guide:AI動画生成プロンプト完全ガイド|10カテゴリ55事例収録 AIコーディングツールは内部でどう動くのか:Claude Codeのアーキテクチャを初心者向けに解説 →