0Pricing
Linux Command Line & Bash Scripting Mastery · Pelajaran

Membuat Mock Perintah dan Stub Alat Eksternal

Timpa PATH dan definisikan biner palsu untuk menguji skrip tanpa menyentuh sistem sebenarnya.

Membuat Mock Perintah dan Stub Alat Eksternal adalah pelajaran Linux Command Line & Bash Scripting Mastery gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Linux Command Line & Bash Scripting Mastery, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Linux Command Line & Bash Scripting Mastery mencakup 4 pelajaran total.

Mengapa Menirukan Perintah dalam Pengujian Bash?

Saat Anda menguji skrip Bash yang memanggil curl, aws, git, atau alat eksternal lainnya, Anda menghadapi masalah: panggilan nyata mengakses jaringan, mengubah keadaan, menghabiskan biaya, atau sekadar gagal di lingkungan CI karena alat tersebut tidak terinstal.

Peniruan berarti mengganti perintah nyata dengan perintah palsu yang Anda kendalikan. Perintah palsu Anda (atau stub) mengembalikan output dan kode keluar yang dapat diprediksi, sehingga pengujian Anda cepat, terisolasi, dan dapat direproduksi.

  • Tidak memerlukan akses jaringan atau cloud
  • Pengujian berjalan dalam hitungan milidetik, bukan detik
  • Anda dapat menyimulasikan kesalahan yang sulit dipicu pada sistem nyata
  • Alur CI tetap bersih dan bebas dependensi

Bash menyediakan mekanisme yang ternyata sangat sederhana untuk melakukan ini: cukup letakkan berkas biner palsu Anda di posisi yang lebih awal dalam $PATH daripada berkas biner yang sebenarnya.

Cara Kerja Pencarian PATH

Saat shell menjalankan perintah seperti curl, shell mencari setiap direktori dalam $PATH dari kiri ke kanan dan menjalankan kecocokan pertama yang ditemukan.

Artinya, jika Anda menambahkan di awal sebuah direktori yang berisi skrip curl milik Anda, shell tidak akan pernah mencapai /usr/bin/curl.

Pola penggantian:

  1. Buat direktori sementara (direktori biner stub Anda)
  2. Tulis berkas eksekusi palsu dengan nama yang sama seperti perintah sebenarnya
  3. Tambahkan direktori tersebut di awal PATH
  4. Jalankan skrip yang diuji — skrip akan memanggil stub Anda, bukan berkas biner yang sebenarnya
  5. Bersihkan direktori sementara setelah pengujian

Hal ini dapat dilakukan tanpa akses root, tanpa mengubah berkas sistem, dan tanpa kerangka kerja khusus.

Membuat Direktori Stub

Pola standar menggunakan mktemp -d untuk membuat direktori sementara terisolasi bagi stub Anda. Setiap pengujian atau rangkaian pengujian memiliki direktorinya sendiri, sehingga mencegah pencemaran antar-pengujian.

Setelah pengujian selesai, hapus direktori tersebut dengan rm -rf. Menggunakan trap memastikan pembersihan tetap dilakukan bahkan saat pengujian berhenti lebih awal karena kesalahan.

#!/usr/bin/env bash
# Setup a stub bin directory for testing

# Create the temp dir
STUB_BIN=$(mktemp -d)

# Always clean up on exit (success, error, or signal)
trap 'rm -rf "$STUB_BIN"' EXIT

# Prepend it to PATH so our stubs take priority
export PATH="$STUB_BIN:$PATH"

echo "Stub bin: $STUB_BIN"
echo "PATH starts with: ${PATH%%:*}"

# Your tests would go here...
echo "Tests complete."

Menulis Stub Pertama Anda

Stub hanyalah berkas eksekusi dengan nama yang sama seperti perintah yang ingin Anda ganti. Stub mencetak output apa pun yang diharapkan oleh skrip yang diuji, lalu keluar dengan kode yang Anda pilih.

Aturan utama untuk stub:

  • Berkas harus dapat dieksekusi (chmod +x)
  • Baris shebang (#!/usr/bin/env bash) wajib ada
  • Cetak output yang akan diuraikan oleh skrip nyata Anda
  • Gunakan exit 0 untuk keberhasilan, dan kode bukan nol untuk kegagalan yang disimulasikan
#!/usr/bin/env bash
# Create a stub for 'curl' that returns a fake HTTP response

STUB_BIN=$(mktemp -d)
trap 'rm -rf "$STUB_BIN"' EXIT
export PATH="$STUB_BIN:$PATH"

# Write the stub
cat > "$STUB_BIN/curl" << 'EOF'
#!/usr/bin/env bash
# Fake curl: always returns a 200 OK with a JSON body
echo '{"status": "ok", "version": "1.2.3"}'
exit 0
EOF
chmod +x "$STUB_BIN/curl"

# Verify the stub is found before the real curl
which curl
curl https://example.com/api/version

Menguji Skrip yang Memanggil curl

Sekarang mari kita gabungkan semuanya. Misalkan Anda memiliki skrip penerapan yang memanggil curl untuk memeriksa titik akhir kesehatan, lalu keluar dengan kesalahan jika layanan tidak sehat. Anda ingin menguji jalur berhasil maupun jalur gagal tanpa menggunakan server nyata.

#!/usr/bin/env bash
# Script under test: check_health.sh
# It calls curl and checks the returned JSON

check_health() {
  local url="$1"
  local response
  response=$(curl -sf "$url")
  if [[ "$response" == *'"healthy":true'* ]]; then
    echo "Service is UP"
    return 0
  else
    echo "Service is DOWN" >&2
    return 1
  fi
}

# ---- Test harness ----
STUB_BIN=$(mktemp -d)
trap 'rm -rf "$STUB_BIN"' EXIT
export PATH="$STUB_BIN:$PATH"

# Happy path stub
cat > "$STUB_BIN/curl" << 'EOF'
#!/usr/bin/env bash
echo '{"healthy":true}'
EOF
chmod +x "$STUB_BIN/curl"

check_health "http://fake-host/health" && echo "PASS: healthy response"

Mensimulasikan Kegagalan Perintah

Salah satu kegunaan stub yang paling berharga adalah mensimulasikan kegagalan yang sulit direproduksi dengan alat nyata—timeout jaringan, kesalahan izin, disk penuh, atau API jarak jauh yang mengembalikan 500.

Untuk mensimulasikan kegagalan, cukup buat stub Anda keluar dengan kode selain nol. Anda juga dapat menulis ke stderr persis seperti yang dilakukan perintah nyata, sehingga penanganan kesalahan dalam skrip Anda benar-benar diuji.

#!/usr/bin/env bash
# Test that check_health handles a curl failure gracefully

check_health() {
  local url="$1"
  local response
  # -f makes curl exit non-zero on HTTP error; -s silences progress
  if ! response=$(curl -sf "$url" 2>/dev/null); then
    echo "ERROR: could not reach $url" >&2
    return 1
  fi
  echo "OK: $response"
}

STUB_BIN=$(mktemp -d)
trap 'rm -rf "$STUB_BIN"' EXIT
export PATH="$STUB_BIN:$PATH"

# Failure stub — simulates a network error (curl exit code 6 = could not resolve host)
cat > "$STUB_BIN/curl" << 'EOF'
#!/usr/bin/env bash
echo 'curl: (6) Could not resolve host: fake-host' >&2
exit 6
EOF
chmod +x "$STUB_BIN/curl"

if ! check_health "http://fake-host/health"; then
  echo "PASS: failure path handled correctly"
fi

Merekam Pemanggilan Stub untuk Verifikasi

Terkadang Anda perlu memastikan bukan hanya apa yang dihasilkan skrip, tetapi juga bagaimana skrip memanggil alat eksternal—argumen yang diteruskan, berapa kali alat tersebut dipanggil, atau dalam urutan apa. Stub pengintai merekam pemanggilannya ke sebuah file.

Setelah pengujian selesai, harness Anda membaca file rekaman tersebut dan memeriksa isinya. Dengan begitu, Anda mendapatkan verifikasi hingga tingkat argumen tanpa kerangka kerja khusus.

#!/usr/bin/env bash
# Spy stub: record every invocation of 'aws' to a log file

STUB_BIN=$(mktemp -d)
CALL_LOG=$(mktemp)
trap 'rm -rf "$STUB_BIN" "$CALL_LOG"' EXIT
export PATH="$STUB_BIN:$PATH"
export CALL_LOG   # make it available inside the stub

cat > "$STUB_BIN/aws" << 'EOF'
#!/usr/bin/env bash
# Append all arguments to the call log
echo "aws $*" >> "$CALL_LOG"
# Return fake S3 output
echo "upload: ./report.pdf to s3://my-bucket/report.pdf"
exit 0
EOF
chmod +x "$STUB_BIN/aws"

# Simulate the script under test calling aws s3 cp
aws s3 cp report.pdf s3://my-bucket/report.pdf
aws s3 cp logs.tar.gz s3://my-bucket/logs.tar.gz

# Verify calls were made with expected arguments
echo "--- Recorded calls ---"
cat "$CALL_LOG"
grep -q 's3://my-bucket/report.pdf' "$CALL_LOG" && echo "PASS: S3 upload verified"

Membuat Stub untuk Beberapa Perintah Sekaligus

Skrip nyata sering memanggil beberapa alat eksternal. Anda dapat membuat stub untuk semuanya di direktori STUB_BIN yang sama. Setiap file stub berdiri sendiri dan dapat mengembalikan keluaran serta kode keluar yang berbeda.

Jaga agar stub tetap minimal: kembalikan hanya hal yang benar-benar diurai oleh skrip yang diuji. Jangan mencoba menyimulasikan setiap flag—cukup bagian yang digunakan skrip Anda.

#!/usr/bin/env bash
# Stub both 'git' and 'docker' for a release script test

STUB_BIN=$(mktemp -d)
trap 'rm -rf "$STUB_BIN"' EXIT
export PATH="$STUB_BIN:$PATH"

# Stub git: pretend we are on tag v2.1.0
cat > "$STUB_BIN/git" << 'EOF'
#!/usr/bin/env bash
case "$*" in
  *"describe --tags"*) echo "v2.1.0" ;;
  *"rev-parse HEAD"*)  echo "abc1234" ;;
  *) echo "[git stub] unhandled: $*" >&2 ; exit 1 ;;
esac
EOF
chmod +x "$STUB_BIN/git"

# Stub docker: pretend build and push succeed
cat > "$STUB_BIN/docker" << 'EOF'
#!/usr/bin/env bash
echo "[docker stub] $*"
exit 0
EOF
chmod +x "$STUB_BIN/docker"

# Simulate the release logic
VERSION=$(git describe --tags)
SHA=$(git rev-parse HEAD)
echo "Building image for version=$VERSION sha=$SHA"
docker build -t "myapp:$VERSION" .
docker push "myapp:$VERSION"

Menggunakan Fungsi sebagai Stub (Tanpa File)

Untuk kasus sederhana, Anda sama sekali tidak perlu menulis file. Anda dapat mendefinisikan fungsi shell dengan nama yang sama seperti perintahnya. Karena fungsi ditemukan sebelum pencarian PATH eksternal, fungsi tersebut otomatis memiliki prioritas.

Ini adalah pendekatan tercepat untuk menguji unit skrip yang dimuat dengan source. Namun, stub berbasis fungsi hanya berfungsi dalam proses shell yang sama—stub tersebut tidak akan terlihat oleh subshell yang dibuat dengan bash -c secara eksplisit atau oleh proses yang dijalankan di latar belakang. Untuk kasus tersebut, gunakan pendekatan berbasis file.

#!/usr/bin/env bash
# Source the script under test (a small helper library)
source_under_test() {
  # Inline the logic we want to test
  get_instance_id() {
    # Would normally call: curl http://169.254.169.254/latest/meta-data/instance-id
    curl -sf http://169.254.169.254/latest/meta-data/instance-id
  }
}
source_under_test

# Override curl with a shell function stub
curl() {
  echo "i-0abc123def456"
  return 0
}
# Export is NOT needed — function is visible in same shell

# Run the function under test
result=$(get_instance_id)
[[ "$result" == "i-0abc123def456" ]] && echo "PASS: instance ID returned" || echo "FAIL"

Mengekspor Fungsi ke Subshell

Ketika skrip yang diuji menjalankan subshell (misalnya bash script.sh atau pipeline), stub fungsi shell yang didefinisikan di proses induk secara bawaan tidak diwariskan. Anda memiliki dua pilihan:

  • Gunakan export -f function_name untuk mengekspor fungsi tersebut—fungsi akan tersedia bagi proses bash turunan
  • Atau gunakan stub berbasis file di direktori STUB_BIN, yang selalu berfungsi lintas batas proses

export -f elegan, tetapi hanya berfungsi dengan bash (bukan sh atau shell lainnya). Utamakan stub berbasis file dalam lingkungan CI poliglot.

#!/usr/bin/env bash
# Demonstrate export -f for subshell-visible function stubs

# Define the stub in the current shell
curl() {
  echo '{"status":"ok"}'
  return 0
}
# Export the function so child bash processes inherit it
export -f curl

# Verify the stub works in a subshell
bash -c '
  response=$(curl -sf http://api.example.com/status)
  echo "Subshell got: $response"
'

# Without export -f, the subshell would call the real curl
# (or fail if curl is not installed)

Mengintegrasikan Stub dengan Kerangka Kerja Pengujian (BATS)

Ketika Anda menggunakan BATS (Bash Automated Testing System), penyiapan stub dilakukan di hook setup() dan pembersihan di teardown(). BATS mengatur ulang lingkungan di antara pengujian, sehingga setiap pengujian mendapatkan direktori stub yang baru.

Variabel BATS seperti $BATS_TEST_TMPDIR otomatis menyediakan direktori sementara untuk setiap pengujian—gunakan ini sebagai pengganti mktemp -d agar kode lebih rapi.

#!/usr/bin/env bats
# File: test_deploy.bats
# Run with: bats test_deploy.bats

setup() {
  # BATS provides a unique tmpdir per test
  export STUB_BIN="$BATS_TEST_TMPDIR/stub_bin"
  mkdir -p "$STUB_BIN"
  export PATH="$STUB_BIN:$PATH"

  # Default stub: healthy service
  cat > "$STUB_BIN/curl" << 'EOF'
#!/usr/bin/env bash
echo '{"healthy":true}'
EOF
  chmod +x "$STUB_BIN/curl"
}

teardown() {
  # BATS auto-removes BATS_TEST_TMPDIR, but explicit is safer
  rm -rf "$STUB_BIN"
}

@test "deploy succeeds when service is healthy" {
  run bash deploy.sh
  [ "$status" -eq 0 ]
  [[ "$output" == *"Deploy complete"* ]]
}

@test "deploy aborts when service is down" {
  # Override the stub for this specific test
  echo -e '#!/usr/bin/env bash\nexit 1' > "$STUB_BIN/curl"
  chmod +x "$STUB_BIN/curl"

  run bash deploy.sh
  [ "$status" -ne 0 ]
}

Uji Pemahaman: Meniru Perintah di Bash

Uji pemahaman Anda tentang peniruan perintah dan pola stub di Bash.

Seorang pengembang menulis pengujian yang mendefinisikan fungsi shell bernama aws untuk membuat stub bagi AWS CLI yang sebenarnya. Pengujian tersebut berjalan baik secara langsung di terminal, tetapi ketika pipeline CI menjalankan skrip yang diuji sebagai bash deploy.sh, stub diabaikan dan perintah aws yang sebenarnya dipanggil.

Apa perbaikan yang benar?

Rekap: Meniru Perintah dan Membuat Stub untuk Alat Eksternal

Anda telah mempelajari perangkat lengkap untuk mengganti perintah nyata dengan tiruan yang terkendali saat menguji skrip Bash.

Teknik utama yang dibahas:

  • Menambahkan awalan pada PATH—buat direktori STUB_BIN dengan mktemp -d, tulis file stub yang dapat dieksekusi di sana, lalu tambahkan direktori tersebut di awal PATH
  • Kode keluar stub—kembalikan 0 untuk keberhasilan dan nilai selain nol untuk menyimulasikan kegagalan tertentu (kesalahan jaringan, izin ditolak, dan sebagainya)
  • Stub pengintai—tambahkan argumen ke file log di dalam stub untuk memastikan bagaimana skrip Anda memanggil alat eksternal
  • Beberapa stub—letakkan beberapa file stub di STUB_BIN yang sama untuk meniru seluruh ekosistem dependensi sekaligus
  • Stub fungsi—definisikan fungsi shell dengan nama yang sama seperti perintah untuk peniruan dalam proses yang sama; gunakan export -f agar dapat menjangkau proses bash turunan
  • Integrasi BATS—gunakan hook setup()/teardown() dan $BATS_TEST_TMPDIR untuk isolasi yang bersih bagi setiap pengujian

Selalu gunakan trap '...' EXIT untuk menjamin pembersihan stub, apa pun hasil pengujiannya. Jaga agar stub tetap minimal—kembalikan hanya hal yang benar-benar diurai oleh skrip Anda. Stub berbasis file adalah pilihan yang paling portabel untuk pipeline CI.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Membuat Mock Perintah dan Stub Alat Eksternal” gratis?

Ya — teks lengkap “Membuat Mock Perintah dan Stub Alat Eksternal” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Linux Command Line & Bash Scripting Mastery, upgrade ke CoddyKit PRO. Kursus Linux Command Line & Bash Scripting Mastery mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Membuat Mock Perintah dan Stub Alat Eksternal”?

Timpa PATH dan definisikan biner palsu untuk menguji skrip tanpa menyentuh sistem sebenarnya. Kamu berlatih Linux Command Line & Bash Scripting Mastery dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Linux Command Line & Bash Scripting Mastery?

Tidak diperlukan pengalaman sebelumnya. Linux Command Line & Bash Scripting Mastery di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Membuat Mock Perintah dan Stub Alat Eksternal” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Linux Command Line & Bash Scripting Mastery ini?

Ya. Setiap pelajaran Linux Command Line & Bash Scripting Mastery menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Menguji Fungsi Unit dengan Bats-core
  2. Membuat Mock Perintah dan Stub Alat Eksternal
  3. Fixture, Environment Sementara, dan Cakupan
  4. Menjalankan Pengujian Shell dalam Pipeline CI
← Kembali ke Linux Command Line & Bash Scripting Mastery