{#- C# test method template
Context variables:
- is_skipped: bool - whether to skip this test
- skip_reason: string - skip reason for [Fact(Skip = "...")]
- description: fixture description
- return_type: "async Task" or "void"
- method_name: test method name (PascalCase)
- async_kw: "await " or empty string
- call_target: target object for function call (class or client instance)
- setup_lines: array of setup statement strings
- call_expr: the function call expression
- expects_error: bool
- exception_class: exception class name to catch
- declared_error_check: string containing the rendered declared-value assertion, or empty
- client_factory_setup: client factory setup code (or empty string)
- has_usable_assertion: bool - whether there's a result to assert on
- result_var: result variable name
- assertions_body: string containing all rendered assertions
- refusal_skip_reason: optional string — when non-empty the fixture declared assertions and
none of them rendered a runnable expectation, so the method carries `[Fact(Skip = ..)]`
instead of `[Fact]`. The rendered skip markers stay in the body, so the refusal is not a
silent skip.
- unrenderable_error_assertions: skip markers for error-path assertions this backend cannot render
#}
{%- if is_skipped %}
[Fact(Skip = "{{ skip_reason }}")]
public void Test_{{ method_name }}()
{
// {{ description }}
}
{%- elif expects_error %}
[Fact]
public {{ return_type }} Test_{{ method_name }}()
{
// {{ description }}
{% if client_factory_setup %}
{{ client_factory_setup }}
{% endif %}
{% if return_type == "async Task" %}
{% if declared_error_check %}
var thrown = await Assert.ThrowsAnyAsync<{{ exception_class }}>(async () =>
{% else %}
await Assert.ThrowsAnyAsync<{{ exception_class }}>(async () =>
{% endif %}
{
{% for line in setup_lines %}
{{ line }}
{% endfor %}
{% if is_streaming %}
await foreach (var item in {{ call_target }}.{{ call_expr }}) { }
{% else %}
await {{ call_target }}.{{ call_expr }};
{% endif %}
});
{% if declared_error_check %}
{{ declared_error_check }}
{% endif %}
{% else %}
{% if declared_error_check %}
var thrown = Assert.ThrowsAny<{{ exception_class }}>(() =>
{% else %}
Assert.ThrowsAny<{{ exception_class }}>(() =>
{% endif %}
{
{% for line in setup_lines %}
{{ line }}
{% endfor %}
{{ call_target }}.{{ call_expr }};
});
{% if declared_error_check %}
{{ declared_error_check }}
{% endif %}
{% endif %}
{% if unrenderable_error_assertions %}
{{ unrenderable_error_assertions }}
{% endif %}
}
{%- else %}
{%- if refusal_skip_reason %}
[Fact(Skip = "{{ refusal_skip_reason }}")]
{% else %}
[Fact]
{% endif %}
public {{ return_type }} Test_{{ method_name }}()
{
// {{ description }}
{% if client_factory_setup %}
{{ client_factory_setup }}
{% endif %}
{% for line in setup_lines %}
{{ line }}
{% endfor %}
{% if is_trait_bridge %}
// Trait bridge registration: Bridge.Register() is self-contained and already
// performs native registration internally — invoke it directly, discard the result.
// Wrap in try/finally so the bridge unregister always runs and the per-test
// registration does not leak into subsequent tests (e.g. displacing the host's
// default backend impl in suites that depend on it).
try
{
{{ call_expr }};
}
finally
{
{% for line in teardown_lines %}
{{ line }}
{% endfor %}
}
{% elif is_streaming %}
await foreach (var item in {{ call_target }}.{{ call_expr }})
{
// Stream items are consumed but assertions are skipped for streaming tests
}
{% elif has_usable_assertion %}
var {{ result_var }} = {{ async_kw }}{{ call_target }}.{{ call_expr }};
{{ assertions_body }}
{% else %}
{{ async_kw }}{{ call_target }}.{{ call_expr }};
{% endif %}
}
{%- endif %}