DEV Community

Altan Sezer Ayan
Altan Sezer Ayan

Posted on • Originally published at Medium

Stop Using Random Strings in JMeter: Generate Algorithmically Correct Mock Data with Mock Jutsu

Load testing is only as good as your test data.

If you're using ${__Random(1000,9999)} to simulate credit card numbers or bank account IDs in JMeter, you're not really testing your system — you're testing it with data that will fail validation before it even reaches your business logic.

Mock Jutsu is a free, zero-dependency JMeter custom functions plugin that generates algorithmically correct mock data directly in your test plans. No scripts, no preprocessing, no external services.


The Problem With Random Test Data

Most JMeter setups generate test data like this:

Credit card: ${__Random(1000000000000000,9999999999999999)}
IBAN: TR${__Random(10,99)}0001234567890123456789
SSN: ${__Random(100000000,999999999)}
Enter fullscreen mode Exit fullscreen mode

These values look real but fail immediately at:

  • Luhn checksum validation (credit cards)
  • MOD-97 validation (IBAN)
  • Format and checksum rules (SSN, TCKN, NIN...)

Your backend rejects them before they touch the database. You're load testing your validation layer, not your system.


Enter Mock Jutsu

Mock Jutsu generates data that passes real validation rules:

${__mockjutsu_financial(iban|TR)}          → TR330006100519786457841326  (MOD-97 valid)
${__mockjutsu_financial(cardnum)}           → 4532015112830366            (Luhn valid)
${__mockjutsu_identity(tckn|TR)}            → 34521678902                 (weighted checksum valid)
${__mockjutsu_identity(ssn|US)}             → 532-88-4071                 (format valid)
${__mockjutsu_banking(swift|TR)}            → AKBKTRIS                    (ISO 9362 valid)
Enter fullscreen mode Exit fullscreen mode

Installation

Option 1 — JMeter Plugins Manager (recommended)

  1. Install Plugins Manager if you haven't already
  2. In JMeter, open Options → Plugins Manager → Available Plugins
  3. Search for "Mock Jutsu", check it, and click Apply Changes and Restart JMeter

Official Plugin Page: https://jmeter-plugins.org/?search=mock-jutsu

Option 2 — Manual JAR

  1. Download mock-jutsu-jmeter-1.1.1.jar from GitHub Releases
  2. Copy to $JMETER_HOME/lib/ext/
  3. Restart JMeter
  4. Open Options → Function Helper Dialog — search for "mockjutsu"

Usage

In any JMeter sampler, config element, or HTTP request body:

{
  "citizenId":  "${__mockjutsu_identity(tckn|TR)}",
  "iban":       "${__mockjutsu_financial(iban|TR)}",
  "cardNumber": "${__mockjutsu_financial(cardnum:visa|TR)}",
  "requestId":  "${__mockjutsu_meta(uuid)}"
}
Enter fullscreen mode Exit fullscreen mode

Syntax:

${__mockjutsu_<category>(type[:qualifier][|locale][|varName][|mask])}
Enter fullscreen mode Exit fullscreen mode

Examples:

${__mockjutsu_financial(cardnum)}                     → 4532015112830366
${__mockjutsu_financial(cardnum:visa|mask)}           → 4532 01** **** 0366  (PCI DSS masked)
${__mockjutsu_financial(cardnum:visa|TR|myCard)}      → stores result in ${myCard}
${__mockjutsu_meta(reverse_regex:[A-Z]{3}\d{4})}      → XKM7291
Enter fullscreen mode Exit fullscreen mode

Groovy / JSR223 Sampler — Direct Java API

All 390+ types are also callable directly from a JSR223 Sampler (Groovy) without the ${__mockjutsu_xxx} expression syntax, using MockJutsuRegistry as the single entry point:

import com.mockjutsu.jmeter.MockJutsuRegistry
import com.mockjutsu.jmeter.MaskerUtil

// Basic: type + locale
def citizenId = MockJutsuRegistry.generate("tckn",    "TR")
def iban      = MockJutsuRegistry.generate("iban",    "TR")
def cardNum   = MockJutsuRegistry.generate("cardnum", "TR", "visa")  // with qualifier
def requestId = MockJutsuRegistry.generate("uuid",    "")

// Store in JMeter variables for use in downstream samplers
vars.put("citizenId",  citizenId)
vars.put("iban",       iban)
vars.put("cardNumber", cardNum)
vars.put("requestId",  requestId)

// Build inline JSON body
def body = """{
  "citizenId":  "${citizenId}",
  "iban":       "${iban}",
  "cardNumber": "${cardNum}",
  "requestId":  "${requestId}"
}"""
vars.put("requestBody", body)

// Masking (PCI / GDPR)
def maskedIban = MaskerUtil.mask("iban", iban)
vars.put("ibanMasked", maskedIban)
Enter fullscreen mode Exit fullscreen mode

Use the Java API when you need runtime flexibility — loops, conditionals, or dynamic type selection — that the expression syntax cannot provide.


Generate Any Custom Format With reverse_regex

Not every field maps to a known type like IBAN or SSN. Every system has its own internal IDs, reference numbers, and codes — and they all have a format your API enforces. This is where reverse_regex comes in.

Instead of generating a constant like "ORD-00000001" across all 500 threads, reverse_regex generates a unique, format-compliant value per request:

${__mockjutsu_meta(reverse_regex:ORD-\d{8})}          → ORD-47291830
${__mockjutsu_meta(reverse_regex:TXN[A-Z]{2}\d{10})}  → TXNQR8471920384
${__mockjutsu_meta(reverse_regex:REF-[A-Z]{3}-\d{6})} → REF-KWP-029471
${__mockjutsu_meta(reverse_regex:[A-Z0-9]{12})}        → X7K2M9QR4LPT
${__mockjutsu_meta(reverse_regex:\d{4}/\d{2}/\d{2})}  → 2026/08/07
Enter fullscreen mode Exit fullscreen mode

This matters because many systems deduplicate on these reference fields. If every thread sends the same hardcoded order ID, your test hits duplicate-key errors — and you're not testing throughput, you're testing your dedup logic.

In Groovy, the regex is passed as the qualifier:

import com.mockjutsu.jmeter.MockJutsuRegistry

def orderId  = MockJutsuRegistry.generate("reverse_regex", "", "ORD-\\d{8}")
def txnRef   = MockJutsuRegistry.generate("reverse_regex", "", "TXN[A-Z]{2}\\d{10}")
def batchRef = MockJutsuRegistry.generate("reverse_regex", "", "BATCH-[A-Z0-9]{6}")

vars.put("orderId",  orderId)
vars.put("txnRef",   txnRef)
vars.put("batchRef", batchRef)
Enter fullscreen mode Exit fullscreen mode

No other JMeter function handles this in a single expression. The closest alternative is a BeanShell script with a custom regex library — that's a dependency, a script file, and 20 lines of boilerplate. reverse_regex does it in one line, zero dependencies.


Supported Data Types (390+)

Category Examples
Identity TCKN, SSN, NIN, INN, de_idnr, SIRET, br_cpf, in_aadhaar...
Financial IBAN, credit cards (Visa/MC/Amex/Mir), CVV, PIN, SEPA QR
Banking SWIFT/BIC, routing number, MT940, CAMT053, MICR line
Payments SWIFT MT103, PAIN001, NACHA ACH, SEPA mandate, Fedwire
Health FHIR patient, NHS number, ICD-10, HL7 message, NPI
Capital Markets ISIN, CUSIP, SEDOL, LEI, FIX message, FX pair
Crypto BTC address, ETH address, tx hash, mnemonic, NFT token
MRZ Passport TD3, TD1 (ICAO Doc 9303 valid)
IoT / RFID / NFC RFID UID, NFC tag, MQTT payload, LoRa packet
Location Latitude, longitude, coordinates, timezone
Meta UUID, JWT, Bearer token, IP, MAC address, reverse_regex
Telecom IMEI (Luhn), ICCID, IMSI, MSISDN
Security X.509 cert, CEF log, PCAP hex, CVE ID
Compliance AML risk, KYC doc type, SAR number, PEP status

Full list: https://altansayan.github.io/mock-jutsu-api/


Why Zero Dependencies Matters

The JAR has no runtime dependencies. Drop it in lib/ext/ and it works.
No classpath conflicts, no version hell, no corporate proxy issues downloading transitive dependencies.


Algorithm Guarantees

All generated data passes real checksum and format validation:

Type Algorithm
TCKN d9/d10 Turkish checksum
IBAN MOD-97 (ISO 13616)
Card numbers Luhn
IMEI Luhn
NHS Number Modulo 11
EAN-13/8 GS1 checksum
ISIN Luhn (alphanumeric)
MRZ ICAO Doc 9303 composite check digit
BTC Address Base58Check (SHA256d)
ETH Address Keccak-256 EIP-55
LEI MOD-97 (ISO 17442)

Real-World Use Case: Fintech Load Test

Testing a payment API that validates IBAN + card number combinations:

Thread Group: 500 users, 60s ramp-up

HTTP Request  POST /api/payment
Body:
{
  "sourceIban":  "${__mockjutsu_financial(iban|TR)}",
  "cardNumber":  "${__mockjutsu_financial(cardnum:visa|TR)}",
  "cvv":         "${__mockjutsu_financial(cvv3)}",
  "amount":      "${__Random(100,10000)}",
  "currency":    "TRY",
  "requestId":   "${__mockjutsu_meta(uuid)}"
}
Enter fullscreen mode Exit fullscreen mode

Every request generates a unique, format-valid payload that passes validation and actually reaches your payment processing logic. That's the load test that matters.


Performance

347 of 423 types (82%) average under 0.05 ms at 1,000 concurrent threads. Only 5 types exceed 0.15 ms (OIDC, AI, Prometheus) — pre-generate these via CSV for production load tests.


Links

Top comments (0)