What is the difference between `MockMvcResultHandlers.print()` and `MockMvcResultHandlers.log()`?
answer
- print() -> System.out, unconditional
- log() -> DEBUG via logging framework, gated
- same report body, different sink
- logger: org.springframework.test.web.servlet.result
- log() is safe to commit
basics
~10 sBoth dump the same request/response report. print() writes to System.out (always visible), while log() writes it through SLF4J/commons-logging at DEBUG level, so it only appears if that logger's DEBUG level is enabled.
solid answer
~40 sThey produce the same formatted `MvcResult` report but differ in destination and controllability. `print()` writes unconditionally to `System.out` (or an `OutputStream`/`Writer` you pass). `log()` routes the report through the logging framework at **DEBUG** level under the logger category `org.springframework.test.web.servlet.result` (the `MockMvcResultHandlers` package logger). So `log()` output is gated by your logging config: if that logger is at INFO or higher, nothing prints. That gating is exactly why `log()` is preferable for committed tests — you can leave `.andDo(log())` or `.alwaysDo(log())` in place and it stays silent in normal runs, then flip the log level to DEBUG to diagnose. `print()` is better for a quick, guaranteed-visible dump while you are actively debugging locally.
code
java · 10 linesimport static org.springframework.test.web.servlet.result.MockMvcResultHandlers.log;
// Left in the committed test: silent unless DEBUG is enabled for
// org.springframework.test.web.servlet.result
mockMvc.perform(get("/api/orders/7"))
.andDo(log())
.andExpect(status().isOk());
// application-test.yml (or logback-test.xml):
// logging.level.org.springframework.test.web.servlet.result: DEBUGgo deeper
Know both dump the request/response; print to console, log via the logger.
Name the DEBUG gating and the logger category; explain why log() is commit-safe.
Reason about CI noise, parallel-run interleaving, and standardizing on alwaysDo(log()).
Set a suite-wide diagnostics policy and wire log level toggles into CI for on-demand debugging.
Both `print()` and `log()` come from `MockMvcResultHandlers` and format the **same** report from the `MvcResult` — request line, params, headers, matched handler, resolved exception, ModelAndView, flash map, and the response (status, headers, body, redirects). The difference is purely the **sink** and its **conditionality**. **`print()`** — writes straight to `System.out`. It is unconditional: the report always appears on standard out. Overloads `print(OutputStream)` and `print(Writer)` let you redirect it. Because it bypasses the logging framework, you cannot silence it via log config; you must remove the call. **`log()`** — writes the report using Apache Commons Logging (which Spring bridges to SLF4J/Logback etc.) at **DEBUG** level, under the logger named for the result package, `org.springframework.test.web.servlet.result`. If that logger is not enabled for DEBUG, `log()` emits nothing. This makes it **safe to commit**: leave it in the test (or as `alwaysDo(log())` on the builder) and it is silent under a normal INFO baseline; when a test misbehaves in CI, raise `logging.level.org.springframework.test.web.servlet.result=DEBUG` and the dumps reappear — no code change, no redeploy of the test. **When to use which**: - Local, active debugging, want it *now* regardless of config → `print()`. - Committed suites, opt-in diagnostics, CI-friendly → `log()`. - Need the report in a file/buffer → `print(Writer/OutputStream)`. **Gotchas**: - `print()` under parallel test execution can interleave on `System.out`; the logging framework used by `log()` usually handles concurrent output better and adds thread/timestamp context. - Forgetting `log()` is DEBUG-gated leads to "why do I see nothing?" — check the logger level. - Neither performs assertions; they are diagnostics, unlike `MockMvcResultMatchers`.
- You committed `.andDo(log())` but see no output in CI — why?log() emits at DEBUG under org.springframework.test.web.servlet.result. If that logger is at INFO/WARN (the usual default), it stays silent. Raise the level to DEBUG to see the report.
- Which would you leave permanently in a shared test suite, and why?log() — it is DEBUG-gated so it stays quiet in normal runs but can be turned on via config without editing tests, unlike print() which always spams System.out.
saying these in an interview costs you the question
- Claiming log() and print() dump different content (they format the same report)
- Saying log() always prints (it is DEBUG-gated)
- Thinking print() can be silenced via logging config