ccgx-workflow 1.0.0 → 1.0.1
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.
- package/README.md +37 -5
- package/README.zh-CN.md +35 -5
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +2 -2
- package/dist/shared/{ccgx-workflow.WgUzkiC3.mjs → ccgx-workflow.SJPbUy5_.mjs} +17 -110
- package/package.json +2 -1
- package/templates/commands/agents/phase-runner.md +321 -321
- package/templates/commands/autonomous.md +792 -792
- package/templates/commands/cancel.md +132 -132
- package/templates/commands/debug.md +226 -226
- package/templates/commands/status.md +206 -206
- package/templates/commands/team.md +484 -0
- package/templates/hooks/ccg-session-state.cjs +510 -510
- package/templates/scripts/ccg-phase-runner-launcher.mjs +467 -467
- package/templates/scripts/invoke-model.mjs +64 -0
- package/templates/skills/domains/ai/SKILL.md +35 -35
- package/templates/skills/domains/ai/agent-dev.md +242 -242
- package/templates/skills/domains/ai/llm-security.md +288 -288
- package/templates/skills/domains/ai/rag-system.md +542 -542
- package/templates/skills/domains/architecture/SKILL.md +43 -43
- package/templates/skills/domains/architecture/api-design.md +225 -225
- package/templates/skills/domains/architecture/cloud-native.md +285 -285
- package/templates/skills/domains/architecture/security-arch.md +297 -297
- package/templates/skills/domains/data-engineering/SKILL.md +208 -208
- package/templates/skills/domains/development/SKILL.md +47 -47
- package/templates/skills/domains/development/cpp.md +246 -246
- package/templates/skills/domains/development/go.md +323 -323
- package/templates/skills/domains/development/java.md +277 -277
- package/templates/skills/domains/development/python.md +288 -288
- package/templates/skills/domains/development/rust.md +313 -313
- package/templates/skills/domains/development/shell.md +313 -313
- package/templates/skills/domains/development/typescript.md +277 -277
- package/templates/skills/domains/devops/SKILL.md +40 -40
- package/templates/skills/domains/devops/database.md +217 -217
- package/templates/skills/domains/devops/devsecops.md +198 -198
- package/templates/skills/domains/devops/git-workflow.md +181 -181
- package/templates/skills/domains/devops/testing.md +283 -283
- package/templates/skills/domains/frontend-design/SKILL.md +244 -244
- package/templates/skills/domains/frontend-design/claymorphism/SKILL.md +121 -121
- package/templates/skills/domains/frontend-design/component-patterns.md +202 -202
- package/templates/skills/domains/frontend-design/glassmorphism/SKILL.md +142 -142
- package/templates/skills/domains/frontend-design/liquid-glass/SKILL.md +139 -139
- package/templates/skills/domains/frontend-design/neubrutalism/SKILL.md +145 -145
- package/templates/skills/domains/frontend-design/state-management.md +680 -680
- package/templates/skills/domains/frontend-design/ui-aesthetics.md +110 -110
- package/templates/skills/domains/frontend-design/ux-principles.md +156 -156
- package/templates/skills/domains/infrastructure/SKILL.md +201 -201
- package/templates/skills/domains/mobile/SKILL.md +225 -225
- package/templates/skills/domains/orchestration/SKILL.md +30 -30
- package/templates/skills/domains/orchestration/multi-agent.md +228 -228
- package/templates/skills/domains/security/SKILL.md +73 -73
- package/templates/skills/domains/security/blue-team.md +436 -436
- package/templates/skills/domains/security/code-audit.md +265 -265
- package/templates/skills/domains/security/pentest.md +226 -226
- package/templates/skills/domains/security/red-team.md +374 -374
- package/templates/skills/domains/security/threat-intel.md +372 -372
- package/templates/skills/domains/security/vuln-research.md +369 -369
- package/templates/skills/tools/lib/shared.js +98 -98
- package/templates/skills/tools/override-refusal/SKILL.md +53 -53
- package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -226
|
@@ -1,277 +1,277 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: java
|
|
3
|
-
description: Java 开发。企业级应用、Spring Boot、微服务。当用户提到 Java、Spring、Maven、Gradle、JVM 时使用。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 📜 符箓秘典 · Java
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## Spring Boot
|
|
10
|
-
|
|
11
|
-
### 基础项目
|
|
12
|
-
```java
|
|
13
|
-
@SpringBootApplication
|
|
14
|
-
public class Application {
|
|
15
|
-
public static void main(String[] args) {
|
|
16
|
-
SpringApplication.run(Application.class, args);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Controller
|
|
21
|
-
@RestController
|
|
22
|
-
@RequestMapping("/api/users")
|
|
23
|
-
public class UserController {
|
|
24
|
-
|
|
25
|
-
@Autowired
|
|
26
|
-
private UserService userService;
|
|
27
|
-
|
|
28
|
-
@GetMapping("/{id}")
|
|
29
|
-
public ResponseEntity<User> getUser(@PathVariable Long id) {
|
|
30
|
-
return userService.findById(id)
|
|
31
|
-
.map(ResponseEntity::ok)
|
|
32
|
-
.orElse(ResponseEntity.notFound().build());
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@PostMapping
|
|
36
|
-
public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO dto) {
|
|
37
|
-
User user = userService.create(dto);
|
|
38
|
-
return ResponseEntity.status(HttpStatus.CREATED).body(user);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Service
|
|
43
|
-
@Service
|
|
44
|
-
public class UserService {
|
|
45
|
-
|
|
46
|
-
@Autowired
|
|
47
|
-
private UserRepository userRepository;
|
|
48
|
-
|
|
49
|
-
public Optional<User> findById(Long id) {
|
|
50
|
-
return userRepository.findById(id);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
@Transactional
|
|
54
|
-
public User create(UserDTO dto) {
|
|
55
|
-
User user = new User();
|
|
56
|
-
user.setName(dto.getName());
|
|
57
|
-
user.setEmail(dto.getEmail());
|
|
58
|
-
return userRepository.save(user);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Repository
|
|
63
|
-
@Repository
|
|
64
|
-
public interface UserRepository extends JpaRepository<User, Long> {
|
|
65
|
-
Optional<User> findByEmail(String email);
|
|
66
|
-
List<User> findByNameContaining(String name);
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Entity
|
|
71
|
-
```java
|
|
72
|
-
@Entity
|
|
73
|
-
@Table(name = "users")
|
|
74
|
-
@Data
|
|
75
|
-
@NoArgsConstructor
|
|
76
|
-
@AllArgsConstructor
|
|
77
|
-
public class User {
|
|
78
|
-
|
|
79
|
-
@Id
|
|
80
|
-
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
81
|
-
private Long id;
|
|
82
|
-
|
|
83
|
-
@Column(nullable = false)
|
|
84
|
-
private String name;
|
|
85
|
-
|
|
86
|
-
@Column(unique = true, nullable = false)
|
|
87
|
-
private String email;
|
|
88
|
-
|
|
89
|
-
@CreatedDate
|
|
90
|
-
private LocalDateTime createdAt;
|
|
91
|
-
|
|
92
|
-
@LastModifiedDate
|
|
93
|
-
private LocalDateTime updatedAt;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// DTO
|
|
97
|
-
@Data
|
|
98
|
-
public class UserDTO {
|
|
99
|
-
@NotBlank(message = "Name is required")
|
|
100
|
-
private String name;
|
|
101
|
-
|
|
102
|
-
@Email(message = "Invalid email")
|
|
103
|
-
@NotBlank(message = "Email is required")
|
|
104
|
-
private String email;
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### 配置
|
|
109
|
-
```yaml
|
|
110
|
-
# application.yml
|
|
111
|
-
spring:
|
|
112
|
-
datasource:
|
|
113
|
-
url: jdbc:postgresql://localhost:5432/mydb
|
|
114
|
-
username: ${DB_USER}
|
|
115
|
-
password: ${DB_PASS}
|
|
116
|
-
jpa:
|
|
117
|
-
hibernate:
|
|
118
|
-
ddl-auto: update
|
|
119
|
-
show-sql: true
|
|
120
|
-
|
|
121
|
-
server:
|
|
122
|
-
port: 8080
|
|
123
|
-
|
|
124
|
-
logging:
|
|
125
|
-
level:
|
|
126
|
-
root: INFO
|
|
127
|
-
com.myapp: DEBUG
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## 异常处理
|
|
131
|
-
|
|
132
|
-
```java
|
|
133
|
-
@RestControllerAdvice
|
|
134
|
-
public class GlobalExceptionHandler {
|
|
135
|
-
|
|
136
|
-
@ExceptionHandler(ResourceNotFoundException.class)
|
|
137
|
-
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
|
|
138
|
-
ErrorResponse error = new ErrorResponse(
|
|
139
|
-
HttpStatus.NOT_FOUND.value(),
|
|
140
|
-
ex.getMessage()
|
|
141
|
-
);
|
|
142
|
-
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
146
|
-
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
|
|
147
|
-
String message = ex.getBindingResult().getFieldErrors().stream()
|
|
148
|
-
.map(FieldError::getDefaultMessage)
|
|
149
|
-
.collect(Collectors.joining(", "));
|
|
150
|
-
ErrorResponse error = new ErrorResponse(
|
|
151
|
-
HttpStatus.BAD_REQUEST.value(),
|
|
152
|
-
message
|
|
153
|
-
);
|
|
154
|
-
return ResponseEntity.badRequest().body(error);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 自定义异常
|
|
159
|
-
public class ResourceNotFoundException extends RuntimeException {
|
|
160
|
-
public ResourceNotFoundException(String message) {
|
|
161
|
-
super(message);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## 测试
|
|
167
|
-
|
|
168
|
-
```java
|
|
169
|
-
@SpringBootTest
|
|
170
|
-
@AutoConfigureMockMvc
|
|
171
|
-
class UserControllerTest {
|
|
172
|
-
|
|
173
|
-
@Autowired
|
|
174
|
-
private MockMvc mockMvc;
|
|
175
|
-
|
|
176
|
-
@MockBean
|
|
177
|
-
private UserService userService;
|
|
178
|
-
|
|
179
|
-
@Test
|
|
180
|
-
void shouldGetUser() throws Exception {
|
|
181
|
-
User user = new User(1L, "Alice", "alice@example.com");
|
|
182
|
-
when(userService.findById(1L)).thenReturn(Optional.of(user));
|
|
183
|
-
|
|
184
|
-
mockMvc.perform(get("/api/users/1"))
|
|
185
|
-
.andExpect(status().isOk())
|
|
186
|
-
.andExpect(jsonPath("$.name").value("Alice"));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
@Test
|
|
190
|
-
void shouldCreateUser() throws Exception {
|
|
191
|
-
UserDTO dto = new UserDTO();
|
|
192
|
-
dto.setName("Bob");
|
|
193
|
-
dto.setEmail("bob@example.com");
|
|
194
|
-
|
|
195
|
-
User user = new User(1L, "Bob", "bob@example.com");
|
|
196
|
-
when(userService.create(any())).thenReturn(user);
|
|
197
|
-
|
|
198
|
-
mockMvc.perform(post("/api/users")
|
|
199
|
-
.contentType(MediaType.APPLICATION_JSON)
|
|
200
|
-
.content(objectMapper.writeValueAsString(dto)))
|
|
201
|
-
.andExpect(status().isCreated())
|
|
202
|
-
.andExpect(jsonPath("$.name").value("Bob"));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// 单元测试
|
|
207
|
-
@ExtendWith(MockitoExtension.class)
|
|
208
|
-
class UserServiceTest {
|
|
209
|
-
|
|
210
|
-
@Mock
|
|
211
|
-
private UserRepository userRepository;
|
|
212
|
-
|
|
213
|
-
@InjectMocks
|
|
214
|
-
private UserService userService;
|
|
215
|
-
|
|
216
|
-
@Test
|
|
217
|
-
void shouldFindById() {
|
|
218
|
-
User user = new User(1L, "Alice", "alice@example.com");
|
|
219
|
-
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
|
|
220
|
-
|
|
221
|
-
Optional<User> result = userService.findById(1L);
|
|
222
|
-
|
|
223
|
-
assertTrue(result.isPresent());
|
|
224
|
-
assertEquals("Alice", result.get().getName());
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## 项目结构
|
|
230
|
-
|
|
231
|
-
```
|
|
232
|
-
myproject/
|
|
233
|
-
├── pom.xml / build.gradle
|
|
234
|
-
├── src/
|
|
235
|
-
│ ├── main/
|
|
236
|
-
│ │ ├── java/
|
|
237
|
-
│ │ │ └── com/myapp/
|
|
238
|
-
│ │ │ ├── Application.java
|
|
239
|
-
│ │ │ ├── controller/
|
|
240
|
-
│ │ │ ├── service/
|
|
241
|
-
│ │ │ ├── repository/
|
|
242
|
-
│ │ │ ├── model/
|
|
243
|
-
│ │ │ ├── dto/
|
|
244
|
-
│ │ │ └── config/
|
|
245
|
-
│ │ └── resources/
|
|
246
|
-
│ │ └── application.yml
|
|
247
|
-
│ └── test/
|
|
248
|
-
│ └── java/
|
|
249
|
-
└── target/
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
## 常用依赖
|
|
253
|
-
|
|
254
|
-
```xml
|
|
255
|
-
<!-- pom.xml -->
|
|
256
|
-
<dependencies>
|
|
257
|
-
<dependency>
|
|
258
|
-
<groupId>org.springframework.boot</groupId>
|
|
259
|
-
<artifactId>spring-boot-starter-web</artifactId>
|
|
260
|
-
</dependency>
|
|
261
|
-
<dependency>
|
|
262
|
-
<groupId>org.springframework.boot</groupId>
|
|
263
|
-
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
264
|
-
</dependency>
|
|
265
|
-
<dependency>
|
|
266
|
-
<groupId>org.springframework.boot</groupId>
|
|
267
|
-
<artifactId>spring-boot-starter-validation</artifactId>
|
|
268
|
-
</dependency>
|
|
269
|
-
<dependency>
|
|
270
|
-
<groupId>org.projectlombok</groupId>
|
|
271
|
-
<artifactId>lombok</artifactId>
|
|
272
|
-
</dependency>
|
|
273
|
-
</dependencies>
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
---
|
|
277
|
-
|
|
1
|
+
---
|
|
2
|
+
name: java
|
|
3
|
+
description: Java 开发。企业级应用、Spring Boot、微服务。当用户提到 Java、Spring、Maven、Gradle、JVM 时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 📜 符箓秘典 · Java
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Spring Boot
|
|
10
|
+
|
|
11
|
+
### 基础项目
|
|
12
|
+
```java
|
|
13
|
+
@SpringBootApplication
|
|
14
|
+
public class Application {
|
|
15
|
+
public static void main(String[] args) {
|
|
16
|
+
SpringApplication.run(Application.class, args);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Controller
|
|
21
|
+
@RestController
|
|
22
|
+
@RequestMapping("/api/users")
|
|
23
|
+
public class UserController {
|
|
24
|
+
|
|
25
|
+
@Autowired
|
|
26
|
+
private UserService userService;
|
|
27
|
+
|
|
28
|
+
@GetMapping("/{id}")
|
|
29
|
+
public ResponseEntity<User> getUser(@PathVariable Long id) {
|
|
30
|
+
return userService.findById(id)
|
|
31
|
+
.map(ResponseEntity::ok)
|
|
32
|
+
.orElse(ResponseEntity.notFound().build());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@PostMapping
|
|
36
|
+
public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO dto) {
|
|
37
|
+
User user = userService.create(dto);
|
|
38
|
+
return ResponseEntity.status(HttpStatus.CREATED).body(user);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Service
|
|
43
|
+
@Service
|
|
44
|
+
public class UserService {
|
|
45
|
+
|
|
46
|
+
@Autowired
|
|
47
|
+
private UserRepository userRepository;
|
|
48
|
+
|
|
49
|
+
public Optional<User> findById(Long id) {
|
|
50
|
+
return userRepository.findById(id);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Transactional
|
|
54
|
+
public User create(UserDTO dto) {
|
|
55
|
+
User user = new User();
|
|
56
|
+
user.setName(dto.getName());
|
|
57
|
+
user.setEmail(dto.getEmail());
|
|
58
|
+
return userRepository.save(user);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Repository
|
|
63
|
+
@Repository
|
|
64
|
+
public interface UserRepository extends JpaRepository<User, Long> {
|
|
65
|
+
Optional<User> findByEmail(String email);
|
|
66
|
+
List<User> findByNameContaining(String name);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Entity
|
|
71
|
+
```java
|
|
72
|
+
@Entity
|
|
73
|
+
@Table(name = "users")
|
|
74
|
+
@Data
|
|
75
|
+
@NoArgsConstructor
|
|
76
|
+
@AllArgsConstructor
|
|
77
|
+
public class User {
|
|
78
|
+
|
|
79
|
+
@Id
|
|
80
|
+
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
81
|
+
private Long id;
|
|
82
|
+
|
|
83
|
+
@Column(nullable = false)
|
|
84
|
+
private String name;
|
|
85
|
+
|
|
86
|
+
@Column(unique = true, nullable = false)
|
|
87
|
+
private String email;
|
|
88
|
+
|
|
89
|
+
@CreatedDate
|
|
90
|
+
private LocalDateTime createdAt;
|
|
91
|
+
|
|
92
|
+
@LastModifiedDate
|
|
93
|
+
private LocalDateTime updatedAt;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// DTO
|
|
97
|
+
@Data
|
|
98
|
+
public class UserDTO {
|
|
99
|
+
@NotBlank(message = "Name is required")
|
|
100
|
+
private String name;
|
|
101
|
+
|
|
102
|
+
@Email(message = "Invalid email")
|
|
103
|
+
@NotBlank(message = "Email is required")
|
|
104
|
+
private String email;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 配置
|
|
109
|
+
```yaml
|
|
110
|
+
# application.yml
|
|
111
|
+
spring:
|
|
112
|
+
datasource:
|
|
113
|
+
url: jdbc:postgresql://localhost:5432/mydb
|
|
114
|
+
username: ${DB_USER}
|
|
115
|
+
password: ${DB_PASS}
|
|
116
|
+
jpa:
|
|
117
|
+
hibernate:
|
|
118
|
+
ddl-auto: update
|
|
119
|
+
show-sql: true
|
|
120
|
+
|
|
121
|
+
server:
|
|
122
|
+
port: 8080
|
|
123
|
+
|
|
124
|
+
logging:
|
|
125
|
+
level:
|
|
126
|
+
root: INFO
|
|
127
|
+
com.myapp: DEBUG
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 异常处理
|
|
131
|
+
|
|
132
|
+
```java
|
|
133
|
+
@RestControllerAdvice
|
|
134
|
+
public class GlobalExceptionHandler {
|
|
135
|
+
|
|
136
|
+
@ExceptionHandler(ResourceNotFoundException.class)
|
|
137
|
+
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
|
|
138
|
+
ErrorResponse error = new ErrorResponse(
|
|
139
|
+
HttpStatus.NOT_FOUND.value(),
|
|
140
|
+
ex.getMessage()
|
|
141
|
+
);
|
|
142
|
+
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
146
|
+
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
|
|
147
|
+
String message = ex.getBindingResult().getFieldErrors().stream()
|
|
148
|
+
.map(FieldError::getDefaultMessage)
|
|
149
|
+
.collect(Collectors.joining(", "));
|
|
150
|
+
ErrorResponse error = new ErrorResponse(
|
|
151
|
+
HttpStatus.BAD_REQUEST.value(),
|
|
152
|
+
message
|
|
153
|
+
);
|
|
154
|
+
return ResponseEntity.badRequest().body(error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 自定义异常
|
|
159
|
+
public class ResourceNotFoundException extends RuntimeException {
|
|
160
|
+
public ResourceNotFoundException(String message) {
|
|
161
|
+
super(message);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 测试
|
|
167
|
+
|
|
168
|
+
```java
|
|
169
|
+
@SpringBootTest
|
|
170
|
+
@AutoConfigureMockMvc
|
|
171
|
+
class UserControllerTest {
|
|
172
|
+
|
|
173
|
+
@Autowired
|
|
174
|
+
private MockMvc mockMvc;
|
|
175
|
+
|
|
176
|
+
@MockBean
|
|
177
|
+
private UserService userService;
|
|
178
|
+
|
|
179
|
+
@Test
|
|
180
|
+
void shouldGetUser() throws Exception {
|
|
181
|
+
User user = new User(1L, "Alice", "alice@example.com");
|
|
182
|
+
when(userService.findById(1L)).thenReturn(Optional.of(user));
|
|
183
|
+
|
|
184
|
+
mockMvc.perform(get("/api/users/1"))
|
|
185
|
+
.andExpect(status().isOk())
|
|
186
|
+
.andExpect(jsonPath("$.name").value("Alice"));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@Test
|
|
190
|
+
void shouldCreateUser() throws Exception {
|
|
191
|
+
UserDTO dto = new UserDTO();
|
|
192
|
+
dto.setName("Bob");
|
|
193
|
+
dto.setEmail("bob@example.com");
|
|
194
|
+
|
|
195
|
+
User user = new User(1L, "Bob", "bob@example.com");
|
|
196
|
+
when(userService.create(any())).thenReturn(user);
|
|
197
|
+
|
|
198
|
+
mockMvc.perform(post("/api/users")
|
|
199
|
+
.contentType(MediaType.APPLICATION_JSON)
|
|
200
|
+
.content(objectMapper.writeValueAsString(dto)))
|
|
201
|
+
.andExpect(status().isCreated())
|
|
202
|
+
.andExpect(jsonPath("$.name").value("Bob"));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// 单元测试
|
|
207
|
+
@ExtendWith(MockitoExtension.class)
|
|
208
|
+
class UserServiceTest {
|
|
209
|
+
|
|
210
|
+
@Mock
|
|
211
|
+
private UserRepository userRepository;
|
|
212
|
+
|
|
213
|
+
@InjectMocks
|
|
214
|
+
private UserService userService;
|
|
215
|
+
|
|
216
|
+
@Test
|
|
217
|
+
void shouldFindById() {
|
|
218
|
+
User user = new User(1L, "Alice", "alice@example.com");
|
|
219
|
+
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
|
|
220
|
+
|
|
221
|
+
Optional<User> result = userService.findById(1L);
|
|
222
|
+
|
|
223
|
+
assertTrue(result.isPresent());
|
|
224
|
+
assertEquals("Alice", result.get().getName());
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## 项目结构
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
myproject/
|
|
233
|
+
├── pom.xml / build.gradle
|
|
234
|
+
├── src/
|
|
235
|
+
│ ├── main/
|
|
236
|
+
│ │ ├── java/
|
|
237
|
+
│ │ │ └── com/myapp/
|
|
238
|
+
│ │ │ ├── Application.java
|
|
239
|
+
│ │ │ ├── controller/
|
|
240
|
+
│ │ │ ├── service/
|
|
241
|
+
│ │ │ ├── repository/
|
|
242
|
+
│ │ │ ├── model/
|
|
243
|
+
│ │ │ ├── dto/
|
|
244
|
+
│ │ │ └── config/
|
|
245
|
+
│ │ └── resources/
|
|
246
|
+
│ │ └── application.yml
|
|
247
|
+
│ └── test/
|
|
248
|
+
│ └── java/
|
|
249
|
+
└── target/
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## 常用依赖
|
|
253
|
+
|
|
254
|
+
```xml
|
|
255
|
+
<!-- pom.xml -->
|
|
256
|
+
<dependencies>
|
|
257
|
+
<dependency>
|
|
258
|
+
<groupId>org.springframework.boot</groupId>
|
|
259
|
+
<artifactId>spring-boot-starter-web</artifactId>
|
|
260
|
+
</dependency>
|
|
261
|
+
<dependency>
|
|
262
|
+
<groupId>org.springframework.boot</groupId>
|
|
263
|
+
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
264
|
+
</dependency>
|
|
265
|
+
<dependency>
|
|
266
|
+
<groupId>org.springframework.boot</groupId>
|
|
267
|
+
<artifactId>spring-boot-starter-validation</artifactId>
|
|
268
|
+
</dependency>
|
|
269
|
+
<dependency>
|
|
270
|
+
<groupId>org.projectlombok</groupId>
|
|
271
|
+
<artifactId>lombok</artifactId>
|
|
272
|
+
</dependency>
|
|
273
|
+
</dependencies>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|