oh-my-customcode 0.9.2 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +25 -30
  2. package/dist/cli/index.js +1315 -568
  3. package/dist/index.js +234 -17
  4. package/package.json +1 -1
  5. package/templates/.claude/agents/arch-documenter.md +7 -71
  6. package/templates/.claude/agents/arch-speckit-agent.md +21 -108
  7. package/templates/.claude/agents/be-express-expert.md +8 -58
  8. package/templates/.claude/agents/be-nestjs-expert.md +6 -38
  9. package/templates/.claude/agents/be-springboot-expert.md +11 -56
  10. package/templates/.claude/agents/db-postgres-expert.md +10 -80
  11. package/templates/.claude/agents/db-redis-expert.md +10 -75
  12. package/templates/.claude/agents/db-supabase-expert.md +12 -48
  13. package/templates/.claude/agents/de-airflow-expert.md +8 -45
  14. package/templates/.claude/agents/de-dbt-expert.md +8 -46
  15. package/templates/.claude/agents/de-kafka-expert.md +10 -10
  16. package/templates/.claude/agents/de-pipeline-expert.md +9 -69
  17. package/templates/.claude/agents/de-snowflake-expert.md +9 -62
  18. package/templates/.claude/agents/de-spark-expert.md +10 -54
  19. package/templates/.claude/agents/fe-svelte-agent.md +5 -41
  20. package/templates/.claude/agents/fe-vercel-agent.md +9 -41
  21. package/templates/.claude/agents/fe-vuejs-agent.md +7 -42
  22. package/templates/.claude/agents/lang-java21-expert.md +11 -37
  23. package/templates/.claude/agents/mgr-claude-code-bible.md +22 -207
  24. package/templates/.claude/agents/mgr-creator.md +7 -88
  25. package/templates/.claude/agents/mgr-gitnerd.md +8 -76
  26. package/templates/.claude/agents/mgr-sauron.md +27 -20
  27. package/templates/.claude/agents/mgr-supplier.md +11 -96
  28. package/templates/.claude/agents/mgr-sync-checker.md +9 -70
  29. package/templates/.claude/agents/mgr-updater.md +9 -79
  30. package/templates/.claude/agents/qa-engineer.md +8 -72
  31. package/templates/.claude/agents/qa-planner.md +2 -3
  32. package/templates/.claude/agents/qa-writer.md +6 -76
  33. package/templates/.claude/agents/sys-memory-keeper.md +13 -87
  34. package/templates/.claude/agents/sys-naggy.md +9 -62
  35. package/templates/.claude/agents/tool-bun-expert.md +7 -52
  36. package/templates/.claude/agents/tool-npm-expert.md +6 -64
  37. package/templates/.claude/agents/tool-optimizer.md +7 -60
  38. package/templates/.claude/rules/MAY-optimization.md +16 -80
  39. package/templates/.claude/rules/MUST-agent-design.md +29 -134
  40. package/templates/.claude/rules/MUST-agent-identification.md +9 -88
  41. package/templates/.claude/rules/MUST-continuous-improvement.md +10 -117
  42. package/templates/.claude/rules/MUST-intent-transparency.md +14 -171
  43. package/templates/.claude/rules/MUST-language-policy.md +11 -46
  44. package/templates/.claude/rules/MUST-orchestrator-coordination.md +82 -425
  45. package/templates/.claude/rules/MUST-parallel-execution.md +33 -405
  46. package/templates/.claude/rules/MUST-permissions.md +14 -68
  47. package/templates/.claude/rules/MUST-safety.md +11 -57
  48. package/templates/.claude/rules/MUST-sync-verification.md +49 -205
  49. package/templates/.claude/rules/MUST-tool-identification.md +21 -134
  50. package/templates/.claude/rules/SHOULD-agent-teams.md +22 -166
  51. package/templates/.claude/rules/SHOULD-ecomode.md +15 -123
  52. package/templates/.claude/rules/SHOULD-error-handling.md +19 -88
  53. package/templates/.claude/rules/SHOULD-hud-statusline.md +9 -89
  54. package/templates/.claude/rules/SHOULD-interaction.md +18 -87
  55. package/templates/.claude/rules/SHOULD-memory-integration.md +25 -118
  56. package/templates/.claude/skills/dev-lead-routing/SKILL.md +70 -243
  57. package/templates/.claude/skills/springboot-best-practices/SKILL.md +180 -319
  58. package/templates/.codex/agents/arch-documenter.md +7 -71
  59. package/templates/.codex/agents/arch-speckit-agent.md +21 -108
  60. package/templates/.codex/agents/be-express-expert.md +8 -58
  61. package/templates/.codex/agents/be-nestjs-expert.md +6 -38
  62. package/templates/.codex/agents/be-springboot-expert.md +11 -56
  63. package/templates/.codex/agents/db-postgres-expert.md +10 -80
  64. package/templates/.codex/agents/db-redis-expert.md +10 -75
  65. package/templates/.codex/agents/db-supabase-expert.md +12 -48
  66. package/templates/.codex/agents/de-airflow-expert.md +8 -45
  67. package/templates/.codex/agents/de-dbt-expert.md +8 -46
  68. package/templates/.codex/agents/de-kafka-expert.md +10 -10
  69. package/templates/.codex/agents/de-pipeline-expert.md +9 -69
  70. package/templates/.codex/agents/de-snowflake-expert.md +9 -62
  71. package/templates/.codex/agents/de-spark-expert.md +10 -54
  72. package/templates/.codex/agents/fe-svelte-agent.md +5 -41
  73. package/templates/.codex/agents/fe-vercel-agent.md +9 -41
  74. package/templates/.codex/agents/fe-vuejs-agent.md +7 -42
  75. package/templates/.codex/agents/infra-aws-expert.md +1 -1
  76. package/templates/.codex/agents/infra-docker-expert.md +1 -1
  77. package/templates/.codex/agents/lang-java21-expert.md +11 -37
  78. package/templates/.codex/agents/mgr-claude-code-bible.md +25 -210
  79. package/templates/.codex/agents/mgr-creator.md +7 -88
  80. package/templates/.codex/agents/mgr-gitnerd.md +8 -76
  81. package/templates/.codex/agents/mgr-sauron.md +30 -23
  82. package/templates/.codex/agents/mgr-supplier.md +11 -96
  83. package/templates/.codex/agents/mgr-sync-checker.md +12 -73
  84. package/templates/.codex/agents/mgr-updater.md +9 -79
  85. package/templates/.codex/agents/qa-engineer.md +8 -72
  86. package/templates/.codex/agents/qa-planner.md +2 -3
  87. package/templates/.codex/agents/qa-writer.md +6 -76
  88. package/templates/.codex/agents/sys-memory-keeper.md +13 -87
  89. package/templates/.codex/agents/sys-naggy.md +9 -62
  90. package/templates/.codex/agents/tool-bun-expert.md +7 -52
  91. package/templates/.codex/agents/tool-npm-expert.md +6 -64
  92. package/templates/.codex/agents/tool-optimizer.md +7 -60
  93. package/templates/.codex/rules/MAY-optimization.md +16 -80
  94. package/templates/.codex/rules/MUST-agent-design.md +29 -134
  95. package/templates/.codex/rules/MUST-agent-identification.md +9 -88
  96. package/templates/.codex/rules/MUST-continuous-improvement.md +10 -117
  97. package/templates/.codex/rules/MUST-intent-transparency.md +14 -171
  98. package/templates/.codex/rules/MUST-language-policy.md +11 -46
  99. package/templates/.codex/rules/MUST-orchestrator-coordination.md +82 -425
  100. package/templates/.codex/rules/MUST-parallel-execution.md +33 -405
  101. package/templates/.codex/rules/MUST-permissions.md +14 -68
  102. package/templates/.codex/rules/MUST-safety.md +11 -57
  103. package/templates/.codex/rules/MUST-sync-verification.md +58 -214
  104. package/templates/.codex/rules/MUST-tool-identification.md +22 -135
  105. package/templates/.codex/rules/SHOULD-agent-teams.md +22 -166
  106. package/templates/.codex/rules/SHOULD-ecomode.md +15 -123
  107. package/templates/.codex/rules/SHOULD-error-handling.md +19 -88
  108. package/templates/.codex/rules/SHOULD-hud-statusline.md +9 -89
  109. package/templates/.codex/rules/SHOULD-interaction.md +18 -87
  110. package/templates/.codex/rules/SHOULD-memory-integration.md +25 -118
  111. package/templates/.codex/skills/dev-lead-routing/SKILL.md +70 -243
  112. package/templates/.codex/skills/springboot-best-practices/SKILL.md +180 -319
@@ -4,354 +4,215 @@ description: Spring Boot patterns for enterprise Java applications
4
4
  user-invocable: false
5
5
  ---
6
6
 
7
- ## Purpose
8
-
9
- Apply Spring Boot patterns for building enterprise-grade applications.
10
-
11
7
  ## Rules
12
8
 
13
9
  ### 1. Project Structure
14
-
15
- ```yaml
16
- structure:
17
- layout: layered architecture
18
- packages:
19
- - controller: REST endpoints
20
- - service: Business logic
21
- - repository: Data access
22
- - model/entity: Domain objects
23
- - dto: Data transfer objects
24
- - config: Configuration classes
25
- - exception: Custom exceptions
26
-
27
- example: |
28
- com.example.app/
29
- ├── controller/
30
- │ └── UserController.java
31
- ├── service/
32
- │ ├── UserService.java
33
- │ └── impl/UserServiceImpl.java
34
- ├── repository/
35
- │ └── UserRepository.java
36
- ├── model/
37
- │ └── User.java
38
- ├── dto/
39
- │ ├── UserRequest.java
40
- │ └── UserResponse.java
41
- ├── config/
42
- │ └── SecurityConfig.java
43
- └── exception/
44
- └── UserNotFoundException.java
45
- ```
10
+ Layered architecture: controller (REST), service (business logic), repository (data access), model/entity, dto, config, exception.
46
11
 
47
12
  ### 2. Dependency Injection
48
-
49
- ```yaml
50
- prefer:
51
- - Constructor injection over field injection
52
- - Interface-based dependencies
53
- - @RequiredArgsConstructor with final fields
54
-
55
- patterns: |
56
- // GOOD: Constructor injection
57
- @Service
58
- @RequiredArgsConstructor
59
- public class UserService {
60
- private final UserRepository userRepository;
61
- private final EmailService emailService;
62
- }
63
-
64
- // AVOID: Field injection
65
- @Service
66
- public class UserService {
67
- @Autowired
68
- private UserRepository userRepository; // Not recommended
69
- }
13
+ Constructor injection preferred. Use @RequiredArgsConstructor with final fields. Avoid field injection with @Autowired.
14
+
15
+ ```java
16
+ // GOOD: Constructor injection
17
+ @Service
18
+ @RequiredArgsConstructor
19
+ public class UserService {
20
+ private final UserRepository userRepository;
21
+ private final EmailService emailService;
22
+ }
70
23
  ```
71
24
 
72
25
  ### 3. REST API Design
73
-
74
- ```yaml
75
- controller:
76
- annotations:
77
- - "@RestController"
78
- - "@RequestMapping with base path"
79
- - "@Validated for input validation"
80
-
81
- patterns: |
82
- @RestController
83
- @RequestMapping("/api/v1/users")
84
- @RequiredArgsConstructor
85
- public class UserController {
86
-
87
- private final UserService userService;
88
-
89
- @GetMapping("/{id}")
90
- public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
91
- return ResponseEntity.ok(userService.findById(id));
92
- }
93
-
94
- @PostMapping
95
- @ResponseStatus(HttpStatus.CREATED)
96
- public UserResponse createUser(@Valid @RequestBody UserRequest request) {
97
- return userService.create(request);
98
- }
99
-
100
- @PutMapping("/{id}")
101
- public UserResponse updateUser(
102
- @PathVariable Long id,
103
- @Valid @RequestBody UserRequest request
104
- ) {
105
- return userService.update(id, request);
106
- }
107
-
108
- @DeleteMapping("/{id}")
109
- @ResponseStatus(HttpStatus.NO_CONTENT)
110
- public void deleteUser(@PathVariable Long id) {
111
- userService.delete(id);
112
- }
113
- }
26
+ @RestController + @RequestMapping. Use @Validated for input, ResponseEntity for responses, proper HTTP status codes.
27
+
28
+ ```java
29
+ @RestController
30
+ @RequestMapping("/api/v1/users")
31
+ @RequiredArgsConstructor
32
+ public class UserController {
33
+ private final UserService userService;
34
+
35
+ @GetMapping("/{id}")
36
+ public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
37
+ return ResponseEntity.ok(userService.findById(id));
38
+ }
39
+
40
+ @PostMapping
41
+ @ResponseStatus(HttpStatus.CREATED)
42
+ public UserResponse createUser(@Valid @RequestBody UserRequest request) {
43
+ return userService.create(request);
44
+ }
45
+ }
114
46
  ```
115
47
 
116
48
  ### 4. Service Layer
117
-
118
- ```yaml
119
- principles:
120
- - Business logic in service layer
121
- - Transaction boundaries at service level
122
- - Interface + implementation pattern
123
-
124
- patterns: |
125
- public interface UserService {
126
- UserResponse findById(Long id);
127
- UserResponse create(UserRequest request);
128
- }
129
-
130
- @Service
131
- @Transactional(readOnly = true)
132
- @RequiredArgsConstructor
133
- public class UserServiceImpl implements UserService {
134
-
135
- private final UserRepository userRepository;
136
- private final UserMapper userMapper;
137
-
138
- @Override
139
- public UserResponse findById(Long id) {
140
- User user = userRepository.findById(id)
141
- .orElseThrow(() -> new UserNotFoundException(id));
142
- return userMapper.toResponse(user);
143
- }
144
-
145
- @Override
146
- @Transactional
147
- public UserResponse create(UserRequest request) {
148
- User user = userMapper.toEntity(request);
149
- return userMapper.toResponse(userRepository.save(user));
150
- }
151
- }
49
+ Business logic in services. @Transactional boundaries at service level. Interface + implementation pattern.
50
+
51
+ ```java
52
+ @Service
53
+ @Transactional(readOnly = true)
54
+ @RequiredArgsConstructor
55
+ public class UserServiceImpl implements UserService {
56
+ private final UserRepository userRepository;
57
+
58
+ @Override
59
+ public UserResponse findById(Long id) {
60
+ User user = userRepository.findById(id)
61
+ .orElseThrow(() -> new UserNotFoundException(id));
62
+ return userMapper.toResponse(user);
63
+ }
64
+
65
+ @Override
66
+ @Transactional
67
+ public UserResponse create(UserRequest request) {
68
+ User user = userMapper.toEntity(request);
69
+ return userMapper.toResponse(userRepository.save(user));
70
+ }
71
+ }
152
72
  ```
153
73
 
154
74
  ### 5. Data Access
155
-
156
- ```yaml
157
- repository:
158
- use: Spring Data JPA
159
- custom_queries: "@Query annotation or method naming"
160
-
161
- patterns: |
162
- public interface UserRepository extends JpaRepository<User, Long> {
163
-
164
- Optional<User> findByEmail(String email);
165
-
166
- @Query("SELECT u FROM User u WHERE u.status = :status")
167
- List<User> findByStatus(@Param("status") UserStatus status);
168
-
169
- @Query(value = "SELECT * FROM users WHERE created_at > :date",
170
- nativeQuery = true)
171
- List<User> findRecentUsers(@Param("date") LocalDateTime date);
172
- }
173
-
174
- entity: |
175
- @Entity
176
- @Table(name = "users")
177
- @Getter
178
- @NoArgsConstructor(access = AccessLevel.PROTECTED)
179
- public class User {
180
-
181
- @Id
182
- @GeneratedValue(strategy = GenerationType.IDENTITY)
183
- private Long id;
184
-
185
- @Column(nullable = false, unique = true)
186
- private String email;
187
-
188
- @Enumerated(EnumType.STRING)
189
- private UserStatus status;
190
-
191
- @CreatedDate
192
- private LocalDateTime createdAt;
193
- }
75
+ Spring Data JPA. @Query or method naming for custom queries. @Entity with proper JPA annotations.
76
+
77
+ ```java
78
+ public interface UserRepository extends JpaRepository<User, Long> {
79
+ Optional<User> findByEmail(String email);
80
+
81
+ @Query("SELECT u FROM User u WHERE u.status = :status")
82
+ List<User> findByStatus(@Param("status") UserStatus status);
83
+ }
84
+
85
+ @Entity
86
+ @Table(name = "users")
87
+ @Getter
88
+ @NoArgsConstructor(access = AccessLevel.PROTECTED)
89
+ public class User {
90
+ @Id
91
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
92
+ private Long id;
93
+
94
+ @Column(nullable = false, unique = true)
95
+ private String email;
96
+
97
+ @Enumerated(EnumType.STRING)
98
+ private UserStatus status;
99
+ }
194
100
  ```
195
101
 
196
102
  ### 6. Exception Handling
197
-
198
- ```yaml
199
- global_handler:
200
- use: "@ControllerAdvice"
201
- custom_exceptions: domain-specific
202
-
203
- patterns: |
204
- @RestControllerAdvice
205
- public class GlobalExceptionHandler {
206
-
207
- @ExceptionHandler(UserNotFoundException.class)
208
- @ResponseStatus(HttpStatus.NOT_FOUND)
209
- public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
210
- return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
211
- }
212
-
213
- @ExceptionHandler(MethodArgumentNotValidException.class)
214
- @ResponseStatus(HttpStatus.BAD_REQUEST)
215
- public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
216
- List<String> errors = ex.getBindingResult()
217
- .getFieldErrors()
218
- .stream()
219
- .map(e -> e.getField() + ": " + e.getDefaultMessage())
220
- .toList();
221
- return new ErrorResponse("VALIDATION_ERROR", errors);
222
- }
223
- }
103
+ @RestControllerAdvice for global handling. Domain-specific exceptions with proper HTTP status mapping.
104
+
105
+ ```java
106
+ @RestControllerAdvice
107
+ public class GlobalExceptionHandler {
108
+ @ExceptionHandler(UserNotFoundException.class)
109
+ @ResponseStatus(HttpStatus.NOT_FOUND)
110
+ public ErrorResponse handleUserNotFound(UserNotFoundException ex) {
111
+ return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
112
+ }
113
+
114
+ @ExceptionHandler(MethodArgumentNotValidException.class)
115
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
116
+ public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
117
+ List<String> errors = ex.getBindingResult()
118
+ .getFieldErrors()
119
+ .stream()
120
+ .map(e -> e.getField() + ": " + e.getDefaultMessage())
121
+ .toList();
122
+ return new ErrorResponse("VALIDATION_ERROR", errors);
123
+ }
124
+ }
224
125
  ```
225
126
 
226
127
  ### 7. Configuration
128
+ Profile-based: application-{profile}.yml. @ConfigurationProperties for type-safe config. Externalize sensitive values.
227
129
 
228
130
  ```yaml
229
- profiles:
230
- use: application-{profile}.yml
231
- externalize: sensitive values
232
-
233
- patterns: |
234
- # application.yml
235
- spring:
236
- profiles:
237
- active: ${SPRING_PROFILES_ACTIVE:local}
238
- datasource:
239
- url: ${DATABASE_URL}
240
- username: ${DATABASE_USERNAME}
241
- password: ${DATABASE_PASSWORD}
242
-
243
- # application-local.yml
244
- spring:
245
- datasource:
246
- url: jdbc:h2:mem:testdb
247
- driver-class-name: org.h2.Driver
248
-
249
- configuration_class: |
250
- @Configuration
251
- @ConfigurationProperties(prefix = "app")
252
- @Validated
253
- public class AppProperties {
254
-
255
- @NotBlank
256
- private String name;
257
-
258
- @Min(1)
259
- private int maxConnections;
260
-
261
- // getters, setters
262
- }
131
+ # application.yml
132
+ spring:
133
+ profiles:
134
+ active: ${SPRING_PROFILES_ACTIVE:local}
135
+ datasource:
136
+ url: ${DATABASE_URL}
137
+ username: ${DATABASE_USERNAME}
138
+ password: ${DATABASE_PASSWORD}
263
139
  ```
264
140
 
265
- ### 8. Security
141
+ ```java
142
+ @Configuration
143
+ @ConfigurationProperties(prefix = "app")
144
+ @Validated
145
+ public class AppProperties {
146
+ @NotBlank
147
+ private String name;
148
+
149
+ @Min(1)
150
+ private int maxConnections;
151
+ }
152
+ ```
266
153
 
267
- ```yaml
268
- principles:
269
- - Use Spring Security
270
- - Externalize secrets
271
- - Implement proper authentication
272
-
273
- patterns: |
274
- @Configuration
275
- @EnableWebSecurity
276
- @RequiredArgsConstructor
277
- public class SecurityConfig {
278
-
279
- private final JwtTokenProvider tokenProvider;
280
-
281
- @Bean
282
- public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
283
- return http
284
- .csrf(csrf -> csrf.disable())
285
- .sessionManagement(session ->
286
- session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
287
- .authorizeHttpRequests(auth -> auth
288
- .requestMatchers("/api/v1/auth/**").permitAll()
289
- .requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
290
- .anyRequest().authenticated())
291
- .addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class)
292
- .build();
293
- }
294
- }
154
+ ### 8. Security
155
+ Spring Security with SecurityFilterChain. Externalize secrets. Proper authentication/authorization patterns.
156
+
157
+ ```java
158
+ @Configuration
159
+ @EnableWebSecurity
160
+ @RequiredArgsConstructor
161
+ public class SecurityConfig {
162
+ @Bean
163
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
164
+ return http
165
+ .csrf(csrf -> csrf.disable())
166
+ .sessionManagement(session ->
167
+ session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
168
+ .authorizeHttpRequests(auth -> auth
169
+ .requestMatchers("/api/v1/auth/**").permitAll()
170
+ .requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
171
+ .anyRequest().authenticated())
172
+ .build();
173
+ }
174
+ }
295
175
  ```
296
176
 
297
177
  ### 9. Testing
298
-
299
- ```yaml
300
- layers:
301
- unit: "@MockBean, Mockito"
302
- integration: "@SpringBootTest"
303
- slice: "@WebMvcTest, @DataJpaTest"
304
-
305
- patterns: |
306
- // Controller test
307
- @WebMvcTest(UserController.class)
308
- class UserControllerTest {
309
-
310
- @Autowired
311
- private MockMvc mockMvc;
312
-
313
- @MockBean
314
- private UserService userService;
315
-
316
- @Test
317
- void getUser_shouldReturnUser() throws Exception {
318
- given(userService.findById(1L))
319
- .willReturn(new UserResponse(1L, "test@example.com"));
320
-
321
- mockMvc.perform(get("/api/v1/users/1"))
322
- .andExpect(status().isOk())
323
- .andExpect(jsonPath("$.email").value("test@example.com"));
324
- }
325
- }
326
-
327
- // Repository test
328
- @DataJpaTest
329
- class UserRepositoryTest {
330
-
331
- @Autowired
332
- private UserRepository userRepository;
333
-
334
- @Test
335
- void findByEmail_shouldReturnUser() {
336
- User user = userRepository.save(new User("test@example.com"));
337
-
338
- Optional<User> found = userRepository.findByEmail("test@example.com");
339
-
340
- assertThat(found).isPresent();
341
- assertThat(found.get().getEmail()).isEqualTo("test@example.com");
342
- }
343
- }
178
+ @WebMvcTest (controller), @DataJpaTest (repository), @SpringBootTest (integration), @MockBean for mocking.
179
+
180
+ ```java
181
+ // Controller test
182
+ @WebMvcTest(UserController.class)
183
+ class UserControllerTest {
184
+ @Autowired
185
+ private MockMvc mockMvc;
186
+
187
+ @MockBean
188
+ private UserService userService;
189
+
190
+ @Test
191
+ void getUser_shouldReturnUser() throws Exception {
192
+ given(userService.findById(1L))
193
+ .willReturn(new UserResponse(1L, "test@example.com"));
194
+
195
+ mockMvc.perform(get("/api/v1/users/1"))
196
+ .andExpect(status().isOk())
197
+ .andExpect(jsonPath("$.email").value("test@example.com"));
198
+ }
199
+ }
200
+
201
+ // Repository test
202
+ @DataJpaTest
203
+ class UserRepositoryTest {
204
+ @Autowired
205
+ private UserRepository userRepository;
206
+
207
+ @Test
208
+ void findByEmail_shouldReturnUser() {
209
+ User user = userRepository.save(new User("test@example.com"));
210
+ Optional<User> found = userRepository.findByEmail("test@example.com");
211
+ assertThat(found).isPresent();
212
+ }
213
+ }
344
214
  ```
345
215
 
346
216
  ## Application
347
217
 
348
- When writing Spring Boot code:
349
-
350
- 1. **Always** use constructor injection
351
- 2. **Always** use layered architecture
352
- 3. **Prefer** interface-based services
353
- 4. **Use** DTOs for API contracts
354
- 5. **Handle** exceptions globally
355
- 6. **Externalize** configuration
356
- 7. **Secure** endpoints properly
357
- 8. **Test** each layer appropriately
218
+ Always: constructor injection, layered architecture, DTOs, global exception handling, externalized config, proper security, layer-appropriate tests.