In JUnit 5, what does the @Disabled annotation do, how does putting it on a test class differ from putting it on a single test method, and what is the string argument used for?
answer
- skipped, not passed, not failed
- method = that test; class = whole container incl. @Nested
- optional reason string shows in reports
- no @Enabled to override inside a disabled class
- JUnit 4 @Ignore is the analogue — different package
basics
~20 s@Disabled skips a test instead of running it, reporting it as skipped rather than failed. On a method it skips that method; on a class it skips every test in the class, including its nested classes. The string argument is the reason, shown in reports and IDEs.
solid answer
~50 s`@Disabled` tells JUnit Jupiter not to execute something. The result is reported as **skipped**, not passed and not failed, so it does not turn the build red and it does not prove anything. - On a **method**, only that method is skipped; the rest of the class runs normally. - On a **class**, the whole container is skipped: every `@Test` in it and every `@Nested` class inside it. The class is not even instantiated. The optional `String` value is the reason, and it is surfaced in the console, the IDE and the XML report. Without it JUnit prints a generic default like *"void checkout() is @Disabled"*, which tells a future reader nothing. So the practical rule is: always pass a reason, and make it actionable — what is broken and where to follow it up, such as `@Disabled("flaky under parallel execution — see PROJ-1421")`. A skipped test with no explanation is indistinguishable from an abandoned one.
code
java · 15 linesclass CheckoutTest {
@Test
void chargesCard() { /* runs */ }
@Test
@Disabled("refund API not implemented yet - PROJ-88")
void refundsCard() { /* skipped */ }
}
@Disabled("whole flow blocked by broken sandbox - PROJ-91")
class LegacyPaymentTest {
@Test void a() { /* skipped */ }
@Nested class Inner { @Test void b() { /* skipped too */ } }
}go deeper
State that it skips the test, that class level skips everything inside, and that the string is a reason shown in reports.
Add that skipped is a distinct outcome from passed, and that reasons should carry a ticket reference.
Emphasise that disabling is a deliberate, tracked loss of signal, and that conditional situations belong in conditional annotations instead.
Talk about disabled tests as an inventory the team owns: expiry expectations, visibility in reporting, and the difference between blocked, flaky and obsolete.
## What it is `org.junit.jupiter.api.Disabled` is JUnit 5's unconditional "do not run this" marker — the successor to JUnit 4's `@Ignore`. It can be placed on a test method or on a test class, and it takes one optional `String` attribute: the reason. ## Method level versus class level On a **method**, the method is not executed. Everything else in the class behaves normally: other tests run, and the class-level setup still happens for them. On a **class**, the entire container is disabled. No test in it runs, no `@Nested` class inside it runs, and the class is never instantiated. This is the sharper tool: it removes a whole area of the suite from the signal, which is why class-level disabling deserves more scrutiny in review than a single method. A detail worth knowing: JUnit does not "inherit-cancel" the annotation. There is no `@Enabled` to re-enable one method inside a disabled class — if you need one test of ten to run, disable the other nine, or restructure. ## Reporting A disabled test appears in the results as **skipped**. Consequences: - the build stays green, so nothing forces anyone to notice; - test counts still include it in the total, with a separate skipped count; - IDEs and CI show the reason string next to it, if you supplied one. Extensions can observe it too: an extension implementing `TestWatcher` receives a `testDisabled(context, reason)` callback, which is how teams build reports that list skipped tests and their reasons. If you supply no reason, JUnit generates a default message naming the disabled element. That satisfies the tooling but not the next engineer. ## How to use it well - **Always give a reason, with a ticket.** `@Disabled("awaiting refund API — PROJ-88")` is reviewable; `@Disabled` alone becomes permanent by accident. - **Disable, do not comment out or delete the body.** A commented-out test is invisible to reporting; a disabled one is counted and can be found. - **Do not use it for environment differences.** "Only runs on Linux" or "needs a database URL" is a *conditional* situation; JUnit has built-in conditional annotations for that, and using `@Disabled` throws away the case where the test could have run. - **Never leave it as a way to hide a failure you do not understand.** Skipped is not passed; a disabled assertion is coverage you have silently lost. ## Relationship to JUnit 4 `@Ignore` in JUnit 4 is the direct analogue, also with an optional reason. Migrating is essentially a rename, but note the package: `org.junit.jupiter.api.Disabled`. A stray `org.junit.Ignore` on a Jupiter test does nothing at all — the Jupiter engine does not look for it — which is a classic silent-mistake during migration.
- Why prefer @Disabled over commenting out the test body or deleting the method?A disabled test is still discovered and counted, appears in reports as skipped with its reason, and stays visible to anyone auditing coverage. Commented-out code is invisible to tooling and rots without anyone noticing. Deleting is legitimate when the behaviour genuinely no longer exists — but then delete deliberately, not as a way to silence a failure.
- A JUnit 5 test still runs despite being annotated @Ignore. Why?`@Ignore` is JUnit 4's annotation in `org.junit`; the Jupiter engine does not look for it, so it is simply an unknown annotation and the test executes. The Jupiter equivalent is `org.junit.jupiter.api.Disabled`. Wrong-package imports of this kind are a common and silent migration bug.
saying these in an interview costs you the question
- Saying a disabled test is reported as passing
- Believing one method inside a @Disabled class can be re-enabled with another annotation
- Using @Disabled for environment- or OS-dependent tests instead of a conditional annotation
- Leaving @Disabled with no reason and treating that as acceptable
- Thinking @Disabled removes the test from the total count entirely