bcquality/microsoft/knowledge/testing/asserterror-needs-expectederror-and-code.md
Jesper Schulz-Wedde 3aa3581f95
Some checks failed
Validate knowledge index / validate-index (push) Has been cancelled
Validate frontmatter and structure / validate (push) Has been cancelled
Add testing knowledge: UI handlers, table relations, asserterror, fixtures (P1+P2) (#62)
* Add testing knowledge: UI handlers, table relations, asserterror, fixtures (P1+P2)

Six BC-specific testing-domain knowledge articles in community/knowledge/testing/, each with .good.al/.bad.al samples:

- ui-calls-require-test-handlers
- tablerelation-requires-prerequisite-records
- handlers-enqueue-never-assert
- handlerfunctions-attribute-must-match-ui-path
- asserterror-needs-expectederror-and-code
- use-library-codeunits-for-test-fixtures

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Move testing knowledge from community to microsoft layer

Relocates the six P1+P2 testing-domain articles (18 files: .md + .good.al + .bad.al each) from community/knowledge/testing/ to microsoft/knowledge/testing/ per maintainer request. Pure git-mv rename; no content or frontmatter changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review: merge handler articles, adopt enqueue-driven pattern

Respond to @nikolakukrika's review on #62:

- Merge ui-calls-require-test-handlers, handlerfunctions-attribute-must-match-ui-path
  and handlers-enqueue-never-assert into a single ui-handlers-in-tests article.
- Adopt the enqueue-from-test / dequeue-and-assert-in-handler pattern using
  Assert.ExpectedConfirm/ExpectedMessage (substring match), with Initialize()
  clearing LibraryVariableStorage and AssertEmpty() proving exact call counts.
- asserterror sample now uses Assert.ExpectedTestFieldError + FieldCaption instead
  of hardcoded message/code; article text points to the library helpers.
- Drop the tablerelation article and fold its test-relevant ordering point
  (relations checked on Validate/Insert(true); build parents first) into
  use-library-codeunits-for-test-fixtures.

Article count 198 -> 195.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-09 10:24:51 +02:00

2.2 KiB

bc-version domain keywords technologies countries application-area
all
testing
asserterror
expectederror
expectederrorcode
negative-test
error-code
al
w1
all

Pin asserterror to a specific error with ExpectedError and ExpectedErrorCode

Description

asserterror passes when the guarded statement raises any error at all. That is too permissive for a negative test: a typo, a missing setup record, or a permission failure all raise errors, so a bare asserterror can go green while never exercising the rule it claims to verify — false confidence that the validation works. Constrain it. Assert.ExpectedError(text) checks the message of the error that was actually raised, and Assert.ExpectedErrorCode(code) checks its error code. Together they assert that the specific failure occurred, turning "something went wrong" into "the right thing went wrong for the right reason".

Best Practice

Follow every asserterror with a verification of the error it expects, and prefer the reusable Library Assert helpers over hardcoded literals. For a mandatory-field check, Assert.ExpectedTestFieldError(FieldCaption, ExpectedValue) encapsulates both the message and the TestField code, so the test survives caption or code changes and does not repeat that knowledge in every method. For other errors, pair Assert.ExpectedError with a stable substring — ideally a shared Label, not an inline sentence — and, where known, Assert.ExpectedErrorCode. When a needed check is missing from the shared library, extend Library Assert (or your own assert library) with a helper rather than hardcoding message text and codes across tests; matching on a code or an invariant fragment keeps the test from going blind to the wrong error when a caption is localized.

See sample: asserterror-needs-expectederror-and-code.good.al.

Anti Pattern

asserterror DoInvalid(); with nothing after it. The test asserts only that the call failed somehow; swap the validation for a different bug and the test still passes, certifying a guard that may no longer fire. A negative test that cannot tell one error from another verifies almost nothing.

See sample: asserterror-needs-expectederror-and-code.bad.al.