springboot-tdd — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited springboot-tdd (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
TDD guidance for Spring Boot services with around 90% coverage of real logic (unit + integration), and 100% where it genuinely adds value.
1) Write a failing test first (they should fail) 2) Implement minimal code to pass 3) Refactor with tests green 4) Enforce coverage (JaCoCo)
Every test must satisfy FIRST: Fast (runs in milliseconds), Isolated (no dependence on other tests or shared state), Repeatable (same result on every run and every machine), Self-validating (a single pass/fail with no manual inspection), and Timely (written alongside or before the code, not bolted on afterwards). FIRST is the governing principle for this workflow.
@ExtendWith(MockitoExtension.class)
class MarketServiceTest {
@Mock MarketRepository repo;
@InjectMocks MarketService service;
@Test
void createsMarket() {
// Given
CreateMarketRequest req = new CreateMarketRequest("name", "desc", Instant.now(), List.of("cat"));
when(repo.save(any())).thenAnswer(inv -> inv.getArgument(0));
// When
Market result = service.create(req);
// Then
assertThat(result.name()).isEqualTo("name");
verify(repo).save(any());
}
@Test
void create_whenRepositoryFails_propagatesException() {
// Given
CreateMarketRequest req = new CreateMarketRequest("name", "desc", Instant.now(), List.of("cat"));
when(repo.save(any())).thenThrow(new DataAccessResourceFailureException("db down"));
// When / Then
assertThatThrownBy(() -> service.create(req))
.isInstanceOf(DataAccessResourceFailureException.class);
verify(repo).save(any());
}
@Test
void create_withEmptyCategories_stillCreatesMarket() {
// Given
CreateMarketRequest req = new CreateMarketRequest("name", "desc", Instant.now(), List.of());
when(repo.save(any())).thenAnswer(inv -> inv.getArgument(0));
// When
Market result = service.create(req);
// Then
assertThat(result.categories()).isEmpty();
}
}Patterns:
@ParameterizedTest for variants@WebMvcTest(MarketController.class)
class MarketControllerTest {
@Autowired MockMvc mockMvc;
@MockitoBean MarketService marketService;
@Test
void returnsMarkets() throws Exception {
// Given
when(marketService.list(any())).thenReturn(Page.empty());
// When / Then
mockMvc.perform(get("/api/markets"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.content").isArray());
}
}Use @MockitoBean for mocking Spring beans on Boot 3.4 and newer; the older @MockBean is deprecated. The sibling springboot-verification skill must use the same annotation, so keep the two in sync.
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
class MarketIntegrationTest {
@Autowired MockMvc mockMvc;
@Test
void createsMarket() throws Exception {
mockMvc.perform(post("/api/markets")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"name":"Test","description":"Desc","endDate":"2030-01-01T00:00:00Z","categories":["general"]}
"""))
.andExpect(status().isCreated());
}
}@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(TestContainersConfig.class)
class MarketRepositoryTest {
@Autowired MarketRepository repo;
@Test
void savesAndFinds() {
MarketEntity entity = new MarketEntity();
entity.setName("Test");
repo.save(entity);
Optional<MarketEntity> found = repo.findByName("Test");
assertThat(found).isPresent();
}
}@DynamicPropertySource to inject JDBC URLs into Spring contextMaven snippet:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.14</version>
<executions>
<execution>
<goals><goal>prepare-agent</goal></goals>
</execution>
<execution>
<id>report</id>
<phase>verify</phase>
<goals><goal>report</goal></goals>
</execution>
</executions>
</plugin>assertThat) for readabilityjsonPathassertThatThrownBy(...)class MarketBuilder {
private String name = "Test";
MarketBuilder withName(String name) { this.name = name; return this; }
Market build() { return new Market(null, name, MarketStatus.ACTIVE); }
}mvn -T 4 test or mvn verify./gradlew test jacocoTestReportRemember: Keep tests fast, isolated, and deterministic. Test behavior, not implementation details.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.