You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
| No comment | Enables automatic transactions (default) |
318
+
| No comment | Enables automatic transactions (default) |
319
+
320
+
## Trigger Control During Tests
321
+
322
+
The framework automatically disables database triggers during test execution to ensure true unit test isolation. This prevents external dependencies and side effects from interfering with tests.
323
+
324
+
### How It Works
325
+
326
+
When tests run (either via `tool4d` or from a host project), the framework sets a flag in 4D's shared `Storage`:
327
+
328
+
```4d
329
+
Storage.triggersDisabled.testMode = True
330
+
```
331
+
332
+
This flag remains set for the duration of the test run, allowing triggers in the host project to check and skip execution during testing.
333
+
334
+
### Running Tests from a Host Project
335
+
336
+
When running tests from a host project (not standalone), you **must** pass the host project's Storage object to enable trigger control:
337
+
338
+
```4d
339
+
// In your host project's method to run tests
340
+
var $hostStorage : Object
341
+
var $userParams : Object
342
+
343
+
$hostStorage:=Storage // Pass the host project's Storage
**Important:** Components have separate Storage objects from their host projects. By passing the host's Storage, the test framework can set flags that your host project's triggers can check.
351
+
352
+
### Implementing Trigger Control in Host Projects
353
+
354
+
To make triggers skip execution during tests, add this check at the beginning of each trigger:
355
+
356
+
```4d
357
+
// At the start of your trigger code
358
+
If (Storage.triggersDisabled#Null) && (Storage.triggersDisabled.testMode=True)
359
+
return // Skip trigger execution during tests
360
+
End if
361
+
362
+
// Normal trigger logic continues here...
363
+
```
364
+
365
+
### Example: Complete Trigger Implementation
366
+
367
+
```4d
368
+
// Table trigger with test mode support
369
+
If (Storage.triggersDisabled#Null) && (Storage.triggersDisabled.testMode=True)
370
+
return
371
+
End if
372
+
373
+
// Normal trigger logic
374
+
Case of
375
+
: (Trigger event=On Saving New Record Event)
376
+
// Validate and set default values
377
+
If ([MyTable]requiredField="")
378
+
[MyTable]requiredField:="DefaultValue"
379
+
End if
380
+
381
+
: (Trigger event=On Saving Existing Record Event)
382
+
// Update modification timestamp
383
+
[MyTable]modifiedAt:=Current date
384
+
End case
385
+
```
386
+
387
+
### Benefits of Trigger Control
388
+
389
+
-**True Unit Testing**: Tests can focus on business logic without trigger side effects
390
+
-**Faster Tests**: Skipping triggers reduces test execution time
391
+
-**Test Isolation**: Each test runs in a clean state without trigger interference
392
+
-**Flexibility**: Easily enable triggers for integration tests when needed
393
+
394
+
### Configuring Trigger Behavior
395
+
396
+
The framework provides flexible control over when triggers execute:
397
+
398
+
#### Global Trigger Control via User Parameters
399
+
400
+
Control the default trigger behavior for all tests using the `triggers` parameter:
401
+
402
+
```bash
403
+
# Enable triggers for all tests (default is disabled)
404
+
make test triggers=enabled
405
+
406
+
# Explicitly disable triggers (default behavior)
407
+
make test triggers=disabled
408
+
409
+
# With other parameters
410
+
make test format=json triggers=enabled tags=integration
411
+
```
412
+
413
+
**Default Behavior**: Triggers are **disabled by default** (`triggers=disabled`) to ensure true unit test isolation.
414
+
415
+
#### Per-Test Trigger Control via Comments
416
+
417
+
Individual tests can override the global setting using comment annotations:
418
+
419
+
```4d
420
+
// #triggers: enabled
421
+
Function test_withTriggersEnabled($t : cs.Testing)
422
+
// This test will have triggers enabled regardless of global setting
423
+
// Useful for integration tests that need to verify trigger behavior
424
+
425
+
// #triggers: disabled
426
+
Function test_withTriggersDisabled($t : cs.Testing)
427
+
// This test will have triggers disabled regardless of global setting
428
+
// Useful for unit tests that need isolation
429
+
430
+
Function test_defaultBehavior($t : cs.Testing)
431
+
// No annotation - uses global setting from triggers parameter
432
+
```
433
+
434
+
#### Use Cases
435
+
436
+
**Unit Tests (triggers disabled):**
437
+
```4d
438
+
// #triggers: disabled
439
+
Function test_calculateTotal($t : cs.Testing)
440
+
// Test business logic without trigger side effects
441
+
// Default behavior - no annotation needed
442
+
```
443
+
444
+
**Integration Tests (triggers enabled):**
445
+
```4d
446
+
// #tags: integration
447
+
// #triggers: enabled
448
+
Function test_orderProcessingWithTriggers($t : cs.Testing)
449
+
// Test complete flow including trigger execution
450
+
```
451
+
452
+
**Hybrid Approach:**
453
+
```bash
454
+
# Run unit tests with triggers disabled (default)
455
+
make test-unit
456
+
457
+
# Run integration tests with triggers enabled
458
+
make test-integration triggers=enabled
459
+
```
460
+
461
+
### When to Allow Triggers
462
+
463
+
For integration tests that specifically need to test trigger behavior:
464
+
465
+
1.**Use per-test annotations** with `// #triggers: enabled`
466
+
2.**Enable globally** with `triggers=enabled` parameter for integration test suites
467
+
3.**Tag appropriately** using `// #tags: integration` for filtering
468
+
4.**Test trigger logic directly** by extracting it into testable functions
469
+
5.**Mock trigger behavior** in unit tests using test doubles
470
+
471
+
### Implementation Notes
472
+
473
+
- The `Storage.triggersDisabled.testMode` flag is automatically managed by the test framework
474
+
- Per-test trigger control automatically restores the default behavior after each test
475
+
- No manual cleanup is required - flags persist only for the test process lifetime
476
+
- Works in both interpreted and compiled modes
477
+
- Compatible with parallel test execution - each worker process has its own Storage state
478
+
- Test-level annotations take precedence over global `triggers` parameter
0 commit comments