本文へ移動
cccskills
無料GitHub で公開

backend-testing

Backend Java tests, controller-level stable-boundary tests, JUnit, @Nested, MakeMe builders, @Transactional, parameterized tests. Use when writing or changing backend JUnit tests.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnutスター 50(GitHub 50 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Backend Testing Rules

Style ("small test" practice — stable boundary, data over mocks, focused assertions, concise makeMe): the unit-testing skill — follow that first.

Commands

Run backend verification from the repo root:

CURSOR_DEV=true nix develop -c pnpm backend:verify

When no database migration is involved, this is faster:

CURSOR_DEV=true nix develop -c pnpm backend:test_only

Always run all backend unit tests instead of a selected file or test case.

For dough-test-optimization, use backend:test_only as both the ordinary feedback measurement and profiling run. Per-test timings are the time attributes in backend/build/test-results/test/TEST-*.xml; keep any derived raw profile outside committed files. To count Spring context boots, temporarily add logging.level.org.springframework.test.context.cache=DEBUG to backend/src/test/resources/application.properties (a logback-test.xml logger is overridden by the test profile's logging.level.root=OFF); each rise in the logged missCount is one boot. Revert it afterwards.

Core Principles

Backend application of the "small test" style (unit-testing skill):

  1. Prefer controller (or other HTTP-stable-boundary) tests for behavior users see through HTTP. These tests often do not reference the internal class you edited; cover services/repos via realistic makeMe preconditions and the real DB.
  2. Test services and algorithms directly only when they are an independent, intentional domain-stable contract (pure logic or algorithms).
  3. Keep tests small and focused: one behavior per test and descriptive names that explain the behavior.

Controller-style example:

@Test
void shouldBeAbleToSaveNoteWhenValid() throws UnexpectedNoAccessRightException {
  Note note = makeMe.aNote().creatorAndOwner(userModel).please();
  final NoteRealm noteRealm = controller.show(note);
  assertThat(noteRealm.getId(), equalTo(note.getId()));
}

Prefer injecting the controller on ControllerTestBase (as above). Every Spring test of the test profile extends SpringTestBase (testability package), directly or through ControllerTestBase, so the suite shares one application context. Do not add @AutoConfigureMockMvc or extra @MockitoBean / @TestBean on a subclass unless that exact annotation mix already exists — each unique mix caches another ApplicationContext and Hikari pool; CI MySQL then fails with Too many connections while a local run still passes. To observe a package-private persistence table, query through EntityManager rather than opening a new MockMvc context.

Calling a controller method directly skips request binding. When a multipart or form DTO field name matters (for example a boolean the frontend sends by name), prove it with a request through an @Autowired MockMvc (multipart(...) with the real field name); SpringTestBase already configures MockMvc, so this adds no context.

Independent algorithm example:

@ParameterizedTest
@CsvSource({
  "moon,     partner of earth,          partner of earth",
  "Sedition, word sedition means this,  word [...] means this"
})
void clozeDescription(String title, String markdown, String expectedClozeDescription) {
  assertThat(
      new ClozedString(clozeReplacement, markdown).hide(new NoteTitle(title)).maskedContentAsMarkdown(),
      containsString(expectedClozeDescription));
}

Database Tests

  • Tests use actual database interactions inside the transaction that SpringTestBase rolls back after each test.
  • This gives confidence in database operations and repository behavior.
  • A @Formula field (for example Note.trashedInDatabase) is hydrated only when Hibernate loads the row from the database. An entity persisted or moved earlier in the same persistence context still carries the Java default, so a test that reads such a field through a loaded collection must makeMe.refresh(entity) first. Query-level predicates (Note.JPA_AVAILABLE) evaluate in SQL and need no refresh.
  • A test that signs in through the security filters creates a SPRING_SESSION row in Spring Session's own transaction, outside that rollback. Such a test class is non-transactional and deletes its session rows after each test (see DevelopmentAuthenticationConfigurationTest). Session cookie attributes apply only on the embedded server, so a test asserting them uses webEnvironment = RANDOM_PORT.

Example (TextContentValidatorTest): no restated Spring annotations; makeMe comes from the base.

class TextContentValidatorTest extends SpringTestBase {
  @Autowired Validator validator;

  @Test
  void defaultNoteIsValid() {
    assertThat(validator.validate(makeMe.aNote().inMemoryPlease()), is(empty()));
  }
}

MakeMe Builders

  • Use the central makeMe factory; chain methods; end with please() (or please(boolean) for persistence control).
  • Builders handle relationships and defaults — see unit-testing skill for when to extend them vs set fields in the test.
  • Ownership: prefer notebookOwnedBy(user) so aMemoryTrackerFor(note) inherits the owner.
Note note = makeMe.aNote()
                 .notebookOwnedBy(user)
                 .title("title")
                 .content("description")
                 .please();

Test Organization

  • Group related tests with @Nested.
  • Use @BeforeEach for common setup, keeping setup minimal and relevant to the group.
  • Mocking policy: unit-testing skill. Backend exception: external services only — mock OpenAIClient structured Responses output with OpenAiStructuredResponseMock in controller tests.

Assertions

  • Use assertThat with descriptive matchers; assertThrows for exceptions; @ParameterizedTest when inputs vary but the assertion focus stays the same.
  • Assertion scope and avoiding cross-test redundancy: unit-testing skill.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

backend

無料

Backend Java — Spring Boot controllers/services, JUnit controller tests, MakeMe. Read this first for any backend work. Use when working on the Java Spring backend.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnut502026年10月26日 更新

Backend Java production code, Spring Boot controllers/services/repositories, controller return values, imports, schema ERD pointer. Use when editing backend production Java.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnut502026年10月26日 更新

cli

無料

related to donut CLI. Use when working on donut-cli.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnut502026年10月26日 更新

Set up and run the Donut dev environment on Cursor Cloud VM (no Nix). Use when working on Cloud VM, running tests on Cloud VM, or encountering command errors related to missing nix. Triggers on: cloud VM, cloud agent, no nix available, /workspace path.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnut502026年10月26日 更新

Regenerate docs/database-erd.md from MySQL information_schema (Mermaid ERD: foreign keys and key columns). Use after Flyway schema changes, new migrations, or when the diagram is stale. Triggers on: database ERD, database-erd.md, export_database_erd, schema diagram, ER diagram after migration.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnut502026年10月26日 更新

Database migration, Flyway, SQL migrations, schema changes, database versioning, migration files, squashing historical migrations. Use when adding or changing Flyway migrations or schema.

日本語の概要は準備中です。原文の説明を表示しています。

nerds-odd-e/doughnut502026年10月26日 更新

nerds-odd-e のスキルをすべて見る

このスキルの問題を報告する