Skip to content

Testing & Mocking — cheat sheet

Mandatory. Source: roadmap.md section "Spring Boot > Testing/Mocking", plus JUnit fundamentals from fundamentals/06-testing-junit.md.

JUnit fundamentals

  • Test class location/naming: lives in the same package as the class it tests (the production class); named <ProductionClass>Test.
  • What to test (as scoped for this course, stricter than typical real-world practice): all public methods of a service class with a return value and at least one argument. Skip: main, constructors, equals/hashCode directly, getters/setters directly, Scanner-based input code, and randomness (isolate the testable part instead).
  • Default (package-private) visibility: no modifier at all — visible only within the same package. Lets you keep a method out of the public API while still letting a same-package test class call it directly, instead of making it fully private (untestable) or fully public (over-exposed).
  • Test structure (Arrange-Act-Assert): @Test-annotated method with three stages — prepare input, call the method under test and capture the result, then assert the result against an expected value (e.g. Assertions.assertEquals(expected, result)).
  • Parameterized tests: @ParameterizedTest + @CsvSource({...}) runs the same test body once per row of supplied input/expected-output data, instead of copy-pasting near- identical @Test methods. Each string in @CsvSource is one parameter group; commas within it split into individual positional arguments; '' is an explicit empty string.
  • TDD (three laws): no production code before a failing test exists; write no more of a test than enough to fail; write no more production code than enough to pass. Produces very short red/green cycles. Increasingly debated — not a fit for every situation.
  • F.I.R.S.T.: good tests are Fast, Independent, Repeatable (same result in any environment), Self-validating (clear pass/fail), Timely (written right before the code that satisfies them).
  • Test coverage: percentage of production code actually exercised by tests; IntelliJ has a built-in coverage tool.

Mocking

  • Mocking: creating a fake, controllable stand-in for a real dependency so you can test one unit in isolation, without needing the real DB/network/etc.
  • Mockito: the standard Java mocking framework, typically paired with JUnit.
  • when/thenReturn: when(mock.method(args)).thenReturn(value) stubs what a mock should return when called with the given arguments.
  • verify / verifyNoMoreInteractions: verify(mock).method(args) asserts a method was actually called (optionally how many times); verifyNoMoreInteractions(mock) asserts nothing else happened on that mock beyond what you already verified — catches unexpected extra calls.
  • @MockBean vs @SpyBean:
    • @MockBean replaces a real bean in the Spring context with a full mock (no real behavior unless stubbed).
    • @SpyBean wraps the real bean, so real methods run unless you explicitly stub one — useful when you want mostly-real behavior with one method overridden.
  • RestTemplate / RestClient: Spring's client for making outgoing HTTP calls from your backend to other services (e.g. calling the GitHub API). RestClient is the newer, more fluent replacement for the older RestTemplate.
  • TestRestTemplate / RestTestClient: used in tests to make real HTTP calls against a running instance of your own app (e.g. inside a @SpringBootTest). RestTemplate = calling other services from production code; TestRestTemplate = calling your own app under test.
  • webEnvironment = RANDOM_PORT vs NONE:
    • RANDOM_PORT actually starts an embedded servlet container on a free port, for real end-to-end HTTP integration tests.
    • NONE loads the Spring context without starting a web server — for tests that just need the beans/context, not real HTTP.
  • Unit test vs integration test (contentious in general, but in a Spring context):
    • Unit test: tests one class in isolation, dependencies mocked (Mockito), no Spring context loaded, fast.
    • Integration test: tests multiple components together (e.g. controller + service + a real/test DB), usually via @SpringBootTest which loads some or all of the application context — slower, closer to real behavior.

Practical

  • [ ] Write a few unit tests for a service/controller class (mock the layer below).
  • [ ] Write a few integration tests for one controller (@SpringBootTest, TestRestTemplate).