or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmockmvc-integration.mdreactive-testing.mdsecurity-context-annotations.mdtest-context-management.md

security-context-annotations.mddocs/

0

# Security Context Annotations

1

2

Core testing annotations for declarative security context management, providing method and class-level authentication setup without complex configuration. These annotations integrate with Spring Test's `TestExecutionListener` framework to automatically establish security contexts before test execution.

3

4

## Capabilities

5

6

### @WithMockUser

7

8

Creates a mock authenticated user with customizable username, password, roles, and authorities.

9

10

```java { .api }

11

/**

12

* Creates a mock authenticated user for testing

13

* Can be applied to test methods or test classes

14

*/

15

@Target({ElementType.METHOD, ElementType.TYPE})

16

@Retention(RetentionPolicy.RUNTIME)

17

@Inherited

18

@Documented

19

@WithSecurityContext(factory = WithMockUserSecurityContextFactory.class)

20

public @interface WithMockUser {

21

/** Username for the mock user (default: "user") */

22

String value() default "user";

23

24

/** Username for the mock user (takes precedence over value()) */

25

String username() default "";

26

27

/** Password for the mock user (default: "password") */

28

String password() default "password";

29

30

/** User roles, automatically prefixed with "ROLE_" (default: {"USER"}) */

31

String[] roles() default {"USER"};

32

33

/** Granted authorities, not automatically prefixed */

34

String[] authorities() default {};

35

36

/** When to establish the security context */

37

TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD;

38

}

39

```

40

41

**Usage Examples:**

42

43

```java

44

// Method-level with default user

45

@Test

46

@WithMockUser

47

public void testWithDefaultUser() {

48

// Test runs with username="user", roles={"USER"}

49

}

50

51

// Custom username and roles

52

@Test

53

@WithMockUser(username = "admin", roles = {"ADMIN", "USER"})

54

public void testWithAdmin() {

55

// Test runs with admin privileges

56

}

57

58

// Using authorities instead of roles

59

@Test

60

@WithMockUser(authorities = {"READ_PRIVILEGES", "WRITE_PRIVILEGES"})

61

public void testWithCustomAuthorities() {

62

// Test runs with specific authorities (no ROLE_ prefix)

63

}

64

65

// Class-level annotation applies to all methods

66

@WithMockUser(roles = "MANAGER")

67

public class ManagerTests {

68

@Test

69

public void testManagerFeature() {

70

// Inherits manager role from class annotation

71

}

72

73

@Test

74

@WithAnonymousUser // Override class-level annotation

75

public void testAnonymousAccess() {

76

// Runs as anonymous user

77

}

78

}

79

```

80

81

### @WithAnonymousUser

82

83

Creates an anonymous authentication for testing scenarios where no authentication is present.

84

85

```java { .api }

86

/**

87

* Creates anonymous authentication for testing

88

* Can be applied to test methods or test classes

89

*/

90

@Target({ElementType.METHOD, ElementType.TYPE})

91

@Retention(RetentionPolicy.RUNTIME)

92

@Inherited

93

@Documented

94

@WithSecurityContext(factory = WithAnonymousUserSecurityContextFactory.class)

95

public @interface WithAnonymousUser {

96

/** When to establish the security context */

97

TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD;

98

}

99

```

100

101

**Usage Examples:**

102

103

```java

104

@Test

105

@WithAnonymousUser

106

public void testAnonymousAccess() {

107

// Test runs with anonymous authentication

108

// Useful for testing public endpoints or access denied scenarios

109

}

110

111

// Override class-level security annotation

112

@WithMockUser(roles = "USER")

113

public class UserTests {

114

@Test

115

@WithAnonymousUser

116

public void testPublicEndpoint() {

117

// Overrides class-level @WithMockUser

118

}

119

}

120

```

121

122

### @WithUserDetails

123

124

Loads a user via `UserDetailsService` for more realistic testing scenarios using actual user data.

125

126

```java { .api }

127

/**

128

* Loads user via UserDetailsService for testing

129

* Requires a UserDetailsService bean in the test context

130

*/

131

@Target({ElementType.METHOD, ElementType.TYPE})

132

@Retention(RetentionPolicy.RUNTIME)

133

@Inherited

134

@Documented

135

@WithSecurityContext(factory = WithUserDetailsSecurityContextFactory.class)

136

public @interface WithUserDetails {

137

/** Username to lookup via UserDetailsService (default: "user") */

138

String value() default "user";

139

140

/** Specific UserDetailsService bean name to use */

141

String userDetailsServiceBeanName() default "";

142

143

/** When to establish the security context */

144

TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD;

145

}

146

```

147

148

**Usage Examples:**

149

150

```java

151

@Test

152

@WithUserDetails("john.doe@example.com")

153

public void testWithRealUser() {

154

// Loads user "john.doe@example.com" via UserDetailsService

155

// Uses actual user data including roles and authorities

156

}

157

158

@Test

159

@WithUserDetails(value = "admin", userDetailsServiceBeanName = "customUserDetailsService")

160

public void testWithCustomService() {

161

// Uses specific UserDetailsService bean

162

}

163

```

164

165

### @SecurityTestExecutionListeners

166

167

Meta-annotation that enables only Spring Security test execution listeners, useful when testing security features without a full application context.

168

169

```java { .api }

170

/**

171

* Meta-annotation that enables Spring Security TestExecutionListeners

172

* Use when testing security without full Spring context setup

173

*/

174

@Target(ElementType.TYPE)

175

@Retention(RetentionPolicy.RUNTIME)

176

@Inherited

177

@Documented

178

@TestExecutionListeners(

179

inheritListeners = false,

180

listeners = {

181

WithSecurityContextTestExecutionListener.class,

182

ReactorContextTestExecutionListener.class

183

}

184

)

185

public @interface SecurityTestExecutionListeners {

186

}

187

```

188

189

**Usage Examples:**

190

191

```java

192

// Use when you only need security testing without full Spring Boot context

193

@SecurityTestExecutionListeners

194

public class SecurityUnitTests {

195

196

@Test

197

@WithMockUser(roles = "USER")

198

public void testSecurityLogic() {

199

// Test security-related logic without full application context

200

// Only security test execution listeners are enabled

201

}

202

}

203

204

// Useful for lightweight security testing

205

@SecurityTestExecutionListeners

206

public class AuthenticationUnitTests {

207

208

@Test

209

@WithUserDetails("testuser")

210

public void testUserDetailsLogic() {

211

// Tests user details without loading full Spring context

212

// Performance benefits for focused security tests

213

}

214

}

215

```

216

217

### @WithSecurityContext

218

219

Meta-annotation for creating custom security context annotations with custom factory implementations.

220

221

```java { .api }

222

/**

223

* Meta-annotation for creating custom security context annotations

224

* Requires a factory implementation

225

*/

226

@Target({ElementType.ANNOTATION_TYPE})

227

@Retention(RetentionPolicy.RUNTIME)

228

@Inherited

229

@Documented

230

public @interface WithSecurityContext {

231

/** Factory class that creates the SecurityContext */

232

Class<? extends WithSecurityContextFactory<? extends Annotation>> factory();

233

234

/** When to establish the security context */

235

TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD;

236

}

237

```

238

239

**Usage Examples:**

240

241

```java

242

// Custom annotation definition

243

@Target({ElementType.METHOD, ElementType.TYPE})

244

@Retention(RetentionPolicy.RUNTIME)

245

@WithSecurityContext(factory = WithCustomUserSecurityContextFactory.class)

246

public @interface WithCustomUser {

247

String username() default "customUser";

248

String department() default "IT";

249

}

250

251

// Custom factory implementation

252

public class WithCustomUserSecurityContextFactory

253

implements WithSecurityContextFactory<WithCustomUser> {

254

255

@Override

256

public SecurityContext createSecurityContext(WithCustomUser annotation) {

257

SecurityContext context = SecurityContextHolder.createEmptyContext();

258

259

// Create custom authentication with department-specific authorities

260

List<GrantedAuthority> authorities = Arrays.asList(

261

new SimpleGrantedAuthority("ROLE_USER"),

262

new SimpleGrantedAuthority("DEPT_" + annotation.department().toUpperCase())

263

);

264

265

UsernamePasswordAuthenticationToken auth =

266

new UsernamePasswordAuthenticationToken(

267

annotation.username(),

268

"password",

269

authorities

270

);

271

272

context.setAuthentication(auth);

273

return context;

274

}

275

}

276

277

// Usage of custom annotation

278

@Test

279

@WithCustomUser(username = "alice", department = "FINANCE")

280

public void testCustomUser() {

281

// Test runs with custom user having ROLE_USER and DEPT_FINANCE authorities

282

}

283

```

284

285

## Supporting Classes

286

287

### WithSecurityContextFactory Interface

288

289

Factory interface for creating security contexts from annotations.

290

291

```java { .api }

292

/**

293

* Factory interface for creating SecurityContext from annotation

294

* @param <A> The annotation type this factory handles

295

*/

296

public interface WithSecurityContextFactory<A extends Annotation> {

297

/**

298

* Create SecurityContext from the provided annotation

299

* @param annotation The annotation instance with configuration

300

* @return SecurityContext to be used for the test

301

*/

302

SecurityContext createSecurityContext(A annotation);

303

}

304

```

305

306

### Built-in Factory Implementations

307

308

```java { .api }

309

// Factory for @WithMockUser

310

public class WithMockUserSecurityContextFactory

311

implements WithSecurityContextFactory<WithMockUser> {

312

public SecurityContext createSecurityContext(WithMockUser withUser);

313

}

314

315

// Factory for @WithAnonymousUser

316

public class WithAnonymousUserSecurityContextFactory

317

implements WithSecurityContextFactory<WithAnonymousUser> {

318

public SecurityContext createSecurityContext(WithAnonymousUser withAnonymousUser);

319

}

320

321

// Factory for @WithUserDetails

322

public class WithUserDetailsSecurityContextFactory

323

implements WithSecurityContextFactory<WithUserDetails> {

324

public SecurityContext createSecurityContext(WithUserDetails withUserDetails);

325

}

326

```

327

328

### TestExecutionEvent Enum

329

330

Defines when the security context should be established during test execution.

331

332

```java { .api }

333

/**

334

* Defines when SecurityContext should be established

335

*/

336

public enum TestExecutionEvent {

337

/** Before test method execution (default) */

338

TEST_METHOD,

339

340

/** Before test execution, after setup methods */

341

TEST_EXECUTION

342

}

343

```

344

345

## Integration with Spring Test

346

347

### WithSecurityContextTestExecutionListener

348

349

The test execution listener that processes security context annotations.

350

351

```java { .api }

352

/**

353

* TestExecutionListener that processes @WithSecurityContext annotations

354

* Order: 10000 (runs after most other listeners)

355

*/

356

public class WithSecurityContextTestExecutionListener implements TestExecutionListener {

357

// Processes annotations before test method/execution

358

// Clears security context after test completion

359

}

360

```

361

362

### Annotation Processing Order

363

364

1. **Class-level annotations** are processed first

365

2. **Method-level annotations** override class-level settings

366

3. **Security context** is established based on `setupBefore` value

367

4. **Test execution** proceeds with established context

368

5. **Context cleanup** occurs after test completion

369

370

## Common Patterns

371

372

### Method Override Pattern

373

374

```java

375

@WithMockUser(roles = "USER") // Class-level default

376

public class SecurityTests {

377

378

@Test

379

public void testUserFeature() {

380

// Uses class-level USER role

381

}

382

383

@Test

384

@WithMockUser(roles = "ADMIN") // Override for this method

385

public void testAdminFeature() {

386

// Uses ADMIN role

387

}

388

389

@Test

390

@WithAnonymousUser // Override to anonymous

391

public void testPublicAccess() {

392

// No authentication

393

}

394

}

395

```

396

397

### Parameterized Tests

398

399

```java

400

@ParameterizedTest

401

@ValueSource(strings = {"user1", "user2", "admin"})

402

@WithUserDetails // Uses parameter value as username

403

public void testMultipleUsers(String username) {

404

// Test runs for each username via UserDetailsService

405

}

406

```

407

408

### Nested Test Classes

409

410

```java

411

@WithMockUser(roles = "USER")

412

public class SecurityNestedTests {

413

414

@Nested

415

@WithMockUser(roles = "ADMIN") // Overrides parent class annotation

416

class AdminTests {

417

@Test

418

public void testAdminFeature() {

419

// Runs with ADMIN role

420

}

421

}

422

423

@Nested

424

class UserTests {

425

@Test

426

public void testUserFeature() {

427

// Inherits USER role from parent class

428

}

429

}

430

}

431

```