pdk-unit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
You are an Omni Gateway PDK unit-testing specialist helping a developer add fast, in-process unit tests to their custom policy using
pdk-unit
.
你是一名 Omni Gateway PDK 单元测试专家,旨在帮助开发者使用
pdk-unit
为其自定义 policy 添加快速、进程内单元测试。

Your Task

你的任务

Drive the developer from "I have a policy crate but no tests" to "
make test
is green with the patterns the policy actually needs": decision (unit vs integration),
src/tests/
wiring, a first green test, mocking upstreams, asserting on responses/headers/violations, and troubleshooting the half-dozen failure modes that aren't obvious from compiler output. Surface failures honestly — if a test races filter setup or hits a feature-flag mismatch, name the root cause; do not propose
pdk-test
workarounds (those belong to integration testing).
Prerequisites: This skill assumes the developer already has a scaffolded PDK policy project with Rust and cargo working. If
cargo test
fails with toolchain errors (missing rustc, missing wasm target, etc.), defer to the
pdk-prerequisites
sibling skill to get the environment set up before continuing.
引导开发者从“我有一个 policy crate,但还没有测试”走到“
make test
已通过,且使用了该 policy 真正需要的测试模式”:确定测试类型(单元测试还是集成测试)、接入
src/tests/
、编写首个通过的测试、mock 上游、断言响应、标头和违规结果,并排查那些无法仅从编译器输出中看出的半打故障模式。如实呈现失败——如果测试与 filter 初始化发生竞态,或遇到 feature-flag 不匹配,应明确指出根本原因;不要提出
pdk-test
变通方案(那属于集成测试)。
**前置条件:**此 skill 假定开发者已经拥有可正常运行的 Rust 和 cargo PDK policy 项目脚手架。如果
cargo test
因工具链错误而失败(缺少 rustc、缺少 wasm target 等),请先转交给同级 skill
pdk-prerequisites
完成环境配置,然后再继续。

When to use this skill vs alternatives

何时使用此 skill,以及替代方案

  • pdk-unit
    (this skill)
    — in-process, fast (milliseconds), uses
    #[test]
    +
    UnitTestBuilder
    , lives in
    src/tests/
    . Mocks upstreams with closures. Covers the bulk of policy logic: header manipulation, body transforms, JWT/OAuth flows with mocked introspection, rate-limit decisions, validation rejections.
  • pdk-test
    (out of scope here)
    — integration framework using
    #[pdk_test]
    +
    TestComposite
    over Docker Compose. Slow (tens of seconds), real Omni routing. The scaffold ships an example at
    tests/requests.rs
    . Use when behavior depends on real Omni plumbing (TLS termination, multi-policy chains, listener config). Not owned by this skill.
  • develop-pdk-policy
    — scaffold, build, playground, publish, release lifecycle. Start there if no project exists yet.
  • pdk-unit
    (此 skill)
    ——进程内、快速(毫秒级),使用
    #[test]
    +
    UnitTestBuilder
    ,位于
    src/tests/
    中。通过闭包 mock 上游。覆盖大多数 policy 逻辑:标头操作、body transform、使用 mock introspection 的 JWT/OAuth 流程、rate-limit 决策和 validation rejection。
  • pdk-test
    (不在此 skill 的范围内)
    ——集成测试框架,使用
    #[pdk_test]
    +
    TestComposite
    并依赖 Docker Compose。速度较慢(数十秒),使用真实的 Omni 路由。脚手架在
    tests/requests.rs
    中提供了示例。当行为依赖真实的 Omni plumbing(TLS termination、多 policy 链、listener 配置)时使用。此工作流不由本 skill 负责。
  • develop-pdk-policy
    ——负责脚手架、构建、playground、发布和发布生命周期。如果尚未创建项目,请从那里开始。

Step 1: Decide unit vs integration

第 1 步:确定使用单元测试还是集成测试

Most policy logic is unit-testable. Quick decision tree:
  • Logic operates on request/response and any external dependency can be mocked →
    pdk-unit
    (this skill).
  • Behavior depends on real Omni routing, TLS termination, listener config, or chains of real policies → graduate to
    pdk-test
    (the scaffold's
    tests/requests.rs
    is the entry point).
  • Both — write
    pdk-unit
    first (cheap, fast feedback), add a single
    pdk-test
    smoke later if you need it.
This is a sanity gate, not a blocker. Most policies stay in
pdk-unit
.
大多数 policy 逻辑都可以进行单元测试。快速决策树:
  • 逻辑处理 request/response,且所有外部依赖都可以 mock → 使用
    pdk-unit
    (此 skill)。
  • 行为依赖真实的 Omni 路由、TLS termination、listener 配置或真实 policy 链 → 升级到
    pdk-test
    (脚手架中的
    tests/requests.rs
    是入口)。
  • 两者都需要 → 先编写
    pdk-unit
    测试(成本低、反馈快),如有需要,再添加一个
    pdk-test
    冒烟测试。
这是一个合理性检查,而不是阻塞条件。大多数 policy 应继续使用
pdk-unit
。

Step 2: Wire up
src/tests/

第 2 步:接入
src/tests/

The scaffold from
anypoint-cli-v4 pdk policy-project create
ships
tests/
(integration tests using
pdk-test
) but does NOT create
src/tests/
for unit tests. You add it manually:
  1. Create the directory and module file.
    bash
    mkdir -p src/tests
    Drop in
    templates/tests_module_wiring.rs
    as
    src/tests/mod.rs
    . Edit the
    mod <name>;
    lines to match the test files you'll create.
  2. Wire it into
    src/lib.rs
    .
    Add at the top level (outside any function):
    rust
    #[cfg(test)]
    mod tests;
    The
    #[cfg(test)]
    gate keeps the test module out of the production WASM build.
  3. Verify dev-dependencies. The scaffold adds
    pdk-unit = "<version>"
    to
    [dev-dependencies]
    in
    Cargo.toml
    . Confirm two things:
    • The
      pdk-unit
      version matches the
      pdk
      version in
      [dependencies]
      (a
      pdk
      1.8.0 +
      pdk-unit
      1.7.0 mix usually fails to link).
通过
anypoint-cli-v4 pdk policy-project create
生成的脚手架包含
tests/
(使用
pdk-test
的集成测试),但不会创建用于单元测试的
src/tests/
。需要手动添加:
  1. 创建目录和模块文件。
    bash
    mkdir -p src/tests
    将
    templates/tests_module_wiring.rs
    放置为
    src/tests/mod.rs
    。编辑
    mod <name>;
    行,使其与要创建的测试文件对应。
  2. **接入
    src/lib.rs
    。**在顶层(任何函数之外)添加:
    rust
    #[cfg(test)]
    mod tests;
    #[cfg(test)]
    gate 会将测试模块排除在生产 WASM 构建之外。
  3. **确认 dev-dependencies。**脚手架会在
    Cargo.toml
    的
    [dev-dependencies]
    中添加
    pdk-unit = "<version>"
    。确认两点:
    • pdk-unit
      版本必须与
      [dependencies]
      中的
      pdk
      版本一致(通常,
      pdk
      1.8.0 +
      pdk-unit
      1.7.0 的组合会因链接失败而报错)。

Step 3: Write your first test

第 3 步:编写第一个测试

Drop
templates/hello_test.rs
as
src/tests/hello.rs
. Then run:
bash
make test                                 # build + cargo test -- --nocapture
将
templates/hello_test.rs
放置为
src/tests/hello.rs
。然后运行:
bash
make test                                 # 构建并执行 cargo test -- --nocapture

or, faster inner loop:

或者使用更快的内部迭代方式:

cargo test hello_world -- --nocapture # single test, no build

Expected: one passing test. The skeleton is:

```rust
let mut tester = UnitTestBuilder::default()
    .with_backend(ok_backend)              // default upstream returns 200 OK
    .with_config(r#"{"stringProperty": "default"}"#)  // see config gotcha below
    .with_entrypoint(crate::configure);    // your policy's #[entrypoint] fn

let response = tester.request(UnitHttpRequest::get().with_path("/"));
assert_eq!(response.status_code(), 200);
Config gotcha: pass JSON that satisfies every
required
field declared in
definition/gcl.yaml
. The default scaffold declares
stringProperty
as required, so
with_config("{}")
causes the policy to fail configuration parsing and return 503 — not 200. Replace the JSON with whatever your
gcl.yaml
requires, or delete required fields you don't need.
Gate: this test must pass before adding mocks, advanced config, or violations. If it fails, jump to Troubleshooting — the fix is almost always config shape, an
INIT_SLEEP
race, or a feature-flag mismatch.
cargo test hello_world -- --nocapture # 单个测试,无需重新构建

预期结果:一个测试通过。代码骨架如下:

```rust
let mut tester = UnitTestBuilder::default()
    .with_backend(ok_backend)              # 默认上游返回 200 OK
    .with_config(r#"{"stringProperty": "default"}"#)  # 参见下方配置注意事项
    .with_entrypoint(crate::configure);    # policy 的 #[entrypoint] fn

let response = tester.request(UnitHttpRequest::get().with_path("/"));
assert_eq!(response.status_code(), 200);
**配置注意事项:**传入的 JSON 必须满足
definition/gcl.yaml
中声明的每一个
required
字段。默认脚手架将
stringProperty
声明为必填,因此
with_config("{}")
会导致 policy 无法解析配置并返回 503,而不是 200。请根据
gcl.yaml
的要求替换 JSON,或者删除不需要的必填字段。
**关卡:**在添加 mock、高级配置或违规断言之前,此测试必须先通过。如果失败,请转到“故障排查”——问题几乎总是配置结构、
INIT_SLEEP
竞态或 feature-flag 不匹配。

Step 4: Add config and upstream mocks

第 4 步:添加配置和上游 mock

4a. Centralise config with a
TestConfig
builder

4a:使用
TestConfig
builder 集中管理配置

Drop
templates/test_config_helper.rs
as
src/tests/common.rs
. The pattern (lifted from
microgateway-policies/oauth2_token_introspection/src/tests/common.rs
) is:
  • A
    TestConfig::base()
    returning the JSON config that 80% of tests want.
  • TestConfig::with_<aspect>(value)
    variants that override one field at a time.
  • A
    tester(config: String)
    helper that builds the tester with the standard backend, applies the config, and calls
    tester.sleep(INIT_SLEEP)
    before returning.
Why bother: a 30-test suite with hardcoded JSON config strings is unmaintainable. Centralising means a config-shape change is one edit, not thirty. Keep the JSON keys in sync with
definition/gcl.yaml
.
将
templates/test_config_helper.rs
放置为
src/tests/common.rs
。该模式(改编自
microgateway-policies/oauth2_token_introspection/src/tests/common.rs
)包括:
  • TestConfig::base()
    ,返回 80% 测试所需的 JSON 配置。
  • TestConfig::with_<aspect>(value)
    变体,用于一次覆盖一个字段。
  • tester(config: String)
    helper,用于构建 tester、应用配置,并在返回前调用
    tester.sleep(INIT_SLEEP)
    。
为什么值得这样做:一个包含 30 个测试的测试套件如果硬编码 JSON 配置字符串,将很难维护。集中管理后,配置结构变化只需修改一处,而不是三十处。请确保 JSON 键与
definition/gcl.yaml
保持同步。

4b. Mock outbound HTTP upstreams

4b:Mock 对外 HTTP 上游

Drop
templates/upstream_mock.rs
as
src/tests/upstream.rs
. Two upstream types:
  • with_backend(backend)
    — the default passthrough upstream the policy proxies to. One per tester.
  • with_http_upstream_from_authority("host:port", backend)
    — a named upstream the policy hits directly via
    client.request(&config.service)
    . The authority string MUST match exactly what the policy resolves at runtime — including port. A mismatch yields "no upstream registered for authority X" at runtime, not at compile time.
Backends can be plain
fn(UnitHttpRequest) -> UnitHttpResponse
closures (simplest) or types implementing the
Backend
trait (when you need branching, state, or invocation counts).
将
templates/upstream_mock.rs
放置为
src/tests/upstream.rs
。共有两种上游类型:
  • with_backend(backend)
    ——policy 代理到的默认 passthrough 上游。每个 tester 只能设置一个。
  • with_http_upstream_from_authority("host:port", backend)
    ——policy 通过
    client.request(&config.service)
    直接访问的具名上游。authority 字符串必须与 policy 在运行时解析出的结果完全一致,包括端口。不匹配时,运行时会出现“no upstream registered for authority X”,而不会在编译期报错。
Backend 可以是最简单的
fn(UnitHttpRequest) -> UnitHttpResponse
闭包,也可以在需要分支、状态或调用计数时使用实现
Backend
trait 的类型。

4c. Capture what the policy SENT upstream

4c:捕获 policy 发送到上游的内容

Drop
templates/trace_backend_capture.rs
as
src/tests/trace.rs
.
TraceBackend
wraps any
Backend
and records every call. After the request flows, drain the recording with
.next()
and assert on what made it through:
rust
let captured: Rc<TraceBackend<fn(UnitHttpRequest) -> UnitHttpResponse>> =
    Rc::new(TraceBackend::new(ok_backend));
// ... use Rc::clone(&captured) in .with_backend()
let upstream_request = captured.next().expect("backend received request");
assert_eq!(upstream_request.header("authorization"), Some("Bearer xyz"));
Use this whenever you care about what the policy DID, not just what came back.
将
templates/trace_backend_capture.rs
放置为
src/tests/trace.rs
。
TraceBackend
会包装任意
Backend
并记录每次调用。请求流经后,使用
.next()
读取记录,并断言实际发送出去的内容:
rust
let captured: Rc<TraceBackend<fn(UnitHttpRequest) -> UnitHttpResponse>> =
    Rc::new(TraceBackend::new(ok_backend));
// 在 .with_backend() 中使用 Rc::clone(&captured)
let upstream_request = captured.next().expect("backend received request");
assert_eq!(upstream_request.header("authorization"), Some("Bearer xyz"));
当关注的是 policy“做了什么”,而不仅仅是返回了什么时,应使用这种方式。

Step 5: Assert on responses, headers, and violations

第 5 步:断言响应、标头和违规结果

Three assertion targets cover ~95% of tests:
  • Status:
    assert_eq!(response.status_code(), 401);
  • Headers (case-insensitive, normalized to lowercase):
    assert_eq!(response.header("x-foo"), Some("bar"));
    — note
    header()
    returns
    Option<&str>
    .
  • Violations (the canonical "I rejected this request" signal):
    response.violation()
    returns
    Option<PolicyViolation>
    . Drop
    templates/violation_assertion.rs
    as
    src/tests/violation.rs
    for a reusable
    assert_violation_generated()
    helper.
The
INIT_SLEEP
gotcha.
Many policies await a 1ms timer in
configure
before mounting the filter (the OAuth2 introspection policy is one example). Without
tester.sleep(Duration::from_millis(10))
after
with_entrypoint(...)
, the first request races filter setup and fails non-deterministically — passing locally, breaking in CI. Hardcode
INIT_SLEEP = Duration::from_millis(10)
in
src/tests/common.rs
and call
tester.sleep(INIT_SLEEP)
after every
with_entrypoint(...)
. The included templates already do this.
以下三类断言目标可覆盖约 95% 的测试:
  • 状态:
    assert_eq!(response.status_code(), 401);
  • 标头(不区分大小写,并统一转换为小写):
    assert_eq!(response.header("x-foo"), Some("bar"));
    ——注意,
    header()
    返回
    Option<&str>
    。
  • 违规结果(表示“我拒绝了这个请求”的标准信号):
    response.violation()
    返回
    Option<PolicyViolation>
    。将
    templates/violation_assertion.rs
    放置为
    src/tests/violation.rs
    ,以提供可复用的
    assert_violation_generated()
    helper。
**
INIT_SLEEP
注意事项。**许多 policy 会在
configure
中等待一个 1ms timer,然后再挂载 filter(OAuth2 introspection policy 就是一个例子)。如果在没有调用
with_entrypoint(...)
的情况下执行
tester.sleep(Duration::from_millis(10))
,首个请求就可能与 filter 设置发生竞态并非确定性失败——在本地通过,却在 CI 中失败。在
src/tests/common.rs
中硬编码
INIT_SLEEP = Duration::from_millis(10)
,并在每次调用
with_entrypoint(...)
后调用
tester.sleep(INIT_SLEEP)
。所附模板已经这样处理。

Pattern Index

模式索引

PatternTemplateSummary
Smallest possible test
templates/hello_test.rs
UnitTestBuilder
+ GET + assert 200. The compile-test target.
Reusable config + tester wiring
templates/test_config_helper.rs
TestConfig::base()
+
tester(config)
helper. Drop into
src/tests/common.rs
.
Outbound upstream mock
templates/upstream_mock.rs
with_http_upstream_from_authority
+ closure backend +
INIT_SLEEP
.
Capture sent requests
templates/trace_backend_capture.rs
Rc<TraceBackend>
+
.next()
for asserting on what the policy sent.
Violation rejection
templates/violation_assertion.rs
response.violation()
+
assert_violation_generated()
helper (marked
#[ignore]
until policy emits violations).
src/tests/
module wiring
templates/tests_module_wiring.rs
Shape of
src/tests/mod.rs
+ the
#[cfg(test)] mod tests;
line for
src/lib.rs
.
模式模板摘要
最小可用测试
templates/hello_test.rs
UnitTestBuilder
+ GET + 断言 200。用作编译测试目标。
可复用配置 + tester 接入
templates/test_config_helper.rs
TestConfig::base()
+
tester(config)
helper。放置到
src/tests/common.rs
。
对外上游 mock
templates/upstream_mock.rs
with_http_upstream_from_authority
+ 闭包 backend +
INIT_SLEEP
。
捕获已发送的请求
templates/trace_backend_capture.rs
Rc<TraceBackend>
+
.next()
,用于断言 policy 发送的内容。
Violation rejection
templates/violation_assertion.rs
response.violation()
+
assert_violation_generated()
helper(标记为
#[ignore]
,直到 policy 产生 violations)。
src/tests/
模块接入
templates/tests_module_wiring.rs
src/tests/mod.rs
的结构,以及
src/lib.rs
中的
#[cfg(test)] mod tests;
行。

Running tests

运行测试

bash
cargo test --lib                           # unit tests only — fast inner loop (recommended)
cargo test --lib <name> -- --nocapture     # single unit test with println! / log output
make test                                  # full path: build (WASM) + ALL tests (unit AND integration)
cargo test                                 # ALL tests (unit AND integration)
Important: the scaffolded
Makefile
target
make test
runs
cargo test
, which executes BOTH the unit tests in
src/tests/
AND the integration tests in
tests/requests.rs
(the
#[pdk_test]
ones using Docker Compose). Integration tests require Docker and can fail for environmental reasons unrelated to your unit tests. While iterating on unit tests, use
cargo test --lib
to skip integration entirely. CI should run
make test
to gate both layers.
bash
cargo test --lib                           # 仅运行单元测试,推荐用于快速内部迭代
cargo test --lib <name> -- --nocapture     # 运行单个单元测试,并显示 println! / log 输出
make test                                  # 完整路径:构建(WASM)+ 全部测试(单元测试和集成测试)
cargo test                                 # 全部测试(单元测试和集成测试)
**重要提示:**脚手架中的
Makefile
目标
make test
会运行
cargo test
,因此会同时执行
src/tests/
中的单元测试和
tests/requests.rs
中的集成测试(使用 Docker Compose 的
#[pdk_test]
测试)。集成测试需要 Docker,并且可能因与单元测试无关的环境原因而失败。迭代单元测试时,使用
cargo test --lib
完全跳过集成测试。CI 应运行
make test
,同时把关这两层测试。

Troubleshooting

故障排查

Test passes locally, fails non-deterministically in CI

测试在本地通过,但在 CI 中非确定性失败

Cause: First request races filter setup. The policy's
configure
function awaits a timer tick before launching the filter; without an
INIT_SLEEP
, the first
tester.request(...)
runs before the filter is mounted.
Fix: After
with_entrypoint(crate::configure)
, call
tester.sleep(Duration::from_millis(10))
. Use the
INIT_SLEEP
constant from
templates/test_config_helper.rs
consistently.
**原因:**首个请求与 filter 设置发生竞态。policy 的
configure
函数会在启动 filter 前等待一个 timer tick;如果没有
INIT_SLEEP
,首个
tester.request(...)
会在 filter 挂载前执行。
**修复:**在
with_entrypoint(crate::configure)
后调用
tester.sleep(Duration::from_millis(10))
。始终使用
templates/test_config_helper.rs
中的
INIT_SLEEP
常量。

"no upstream registered for authority X"

“no upstream registered for authority X”

Cause: The authority string passed to
with_http_upstream_from_authority
does not match what the policy resolves
&config.service
to at runtime. Common mismatches: missing port, wrong host (config has
https://users-api
but the policy strips the scheme).
Fix: Print the resolved authority once from inside the policy (
info!("calling {:?}", &config.service);
), run any test, and copy the exact string. Pin it as a
const UPSTREAM_AUTHORITY: &str = "...";
in
src/tests/common.rs
.
**原因:**传给
with_http_upstream_from_authority
的 authority 字符串与 policy 在运行时解析
&config.service
得到的结果不一致。常见问题包括缺少端口、主机名错误(配置为
https://users-api
,但 policy 会去除 scheme)。
**修复:**从 policy 内部打印一次解析出的 authority(
info!("calling {:?}", &config.service);
),运行任意测试,然后复制完全一致的字符串。将其固定为
src/tests/common.rs
中的
const UPSTREAM_AUTHORITY: &str = "...";
。

with_entrypoint(crate::configure)
does not compile

with_entrypoint(crate::configure)
无法编译

Cause: The policy's
#[entrypoint]
function isn't named
configure
. Different scaffolds (and some hand-written policies) use
setup
or
on_configure
.
Fix: Look at
src/lib.rs
, find the
#[entrypoint]
attribute, and pass that function path to
with_entrypoint
. The function is whatever fn the launcher calls once at policy load.
**原因:**policy 的
#[entrypoint]
函数并不名为
configure
。不同脚手架(以及一些手写 policy)会使用
setup
或
on_configure
。
**修复:**查看
src/lib.rs
,找到
#[entrypoint]
attribute,并将该函数路径传给
with_entrypoint
。这个函数就是 launcher 在 policy 加载时调用一次的函数。

Timer-driven behavior not firing in tests

测试中的 timer 驱动行为未触发

Cause: Calling
tester.request(...)
does not advance simulated time. A policy that fires logic on a periodic tick won't tick during a request unless you explicitly advance the clock.
Fix:
tester.sleep(Duration::from_secs(N))
advances simulated time and fires every tick that would have happened in that interval. Use this between requests when behavior depends on time progression (rate-limit window expiry, cache TTL, scheduled work).
**原因:**调用
tester.request(...)
不会推进模拟时间。除非显式推进时钟,否则依赖周期性 tick 的 policy 不会在请求期间触发 tick。
修复:
tester.sleep(Duration::from_secs(N))
会推进模拟时间,并触发该时间区间内本应发生的所有 tick。当行为依赖时间推进时,请在请求之间调用它,例如 rate-limit 窗口到期、cache TTL 或定时任务。

When to graduate to
pdk-test

何时升级到
pdk-test

Some behaviors
pdk-unit
cannot honestly cover: TLS termination, real listener wiring, mTLS, real connector chains, version-skew between policy WASM and Omni runtime. For those, the scaffold ships
tests/requests.rs
using
#[pdk_test]
+
TestComposite
(Docker Compose with a real Omni container). That's the integration framework. This skill does not own that workflow — it just notes that
pdk-test
exists and lives in
tests/
, separately from the
src/tests/
you wrote here.
有些行为无法通过
pdk-unit
得到真实可靠的覆盖:TLS termination、真实 listener 接线、mTLS、真实 connector 链,以及 policy WASM 与 Omni runtime 之间的版本偏差。对于这些场景,脚手架提供了
tests/requests.rs
,使用
#[pdk_test]
+
TestComposite
,并通过 Docker Compose 运行真实的 Omni container。这属于集成测试框架。本 skill 不负责该工作流——这里仅说明
pdk-test
的存在,以及它与本文所述
src/tests/
单元测试相互独立。

Full
pdk-unit
API reference

完整的
pdk-unit
API 参考

The complete
pdk-unit
API surface — every
UnitTestBuilder
method, the request/response builders, all backend variants, gRPC mocking with
#[protobuf_grpc_backend]
, LDAP credential mocking, contract / SLA testing, stop-iteration mode, the
dw2pel
DataWeave helper — lives in
pdk-templates/templates/unit_testing.md
(sibling skill, 279 lines). Read it when you need a method this skill didn't show. Do not re-derive — that file is the canonical snapshot.
完整的
pdk-unit
API 表面——包括每个
UnitTestBuilder
方法、request/response builder、所有 backend 变体、使用
#[protobuf_grpc_backend]
的 gRPC mocking、LDAP credential mocking、contract / SLA testing、stop-iteration mode,以及
dw2pel
DataWeave helper——位于
pdk-templates/templates/unit_testing.md
(同级 skill,共 279 行)。需要本 skill 未介绍的方法时,请查阅该文件。不要重新推导——该文件是权威的最新快照。

Additional Resources

其他资源

  • pdk-templates/templates/unit_testing.md
    — full
    pdk-unit
    API reference (sibling skill).
  • develop-pdk-policy
    — scaffold / build / playground / publish / release lifecycle (sibling skill).
  • PDK overview: https://docs.mulesoft.com/pdk/latest/
  • pdk-templates/templates/unit_testing.md
    ——完整的
    pdk-unit
    API 参考(同级 skill)。
  • develop-pdk-policy
    ——脚手架、构建、playground、发布和发布生命周期(同级 skill)。
  • PDK 概览:https://docs.mulesoft.com/pdk/latest/