Mock Mode Guide
Understanding Mock Mode in Brobotโ
Brobot's mock mode provides a powerful testing framework that simulates GUI automation without requiring actual screen interaction. This is essential for:
- CI/CD pipelines where GUI access is unavailable
- Unit testing automation logic without GUI dependencies
- Development when the target application is unavailable
- Testing state transitions and automation flow logic
Mock Mode vs Headless Modeโ
Important Distinction:
- Mock Mode (
brobot.mock): Simulates actions and pattern matching for testing without real screen interaction - Headless Mode (
brobot.headless): Indicates no display is available (e.g., server environments, CI/CD)
These are independent settings:
- You can run mock mode with a display (development testing)
- You can run mock mode without a display (CI/CD testing)
- Headless environments typically use mock mode, but mock mode doesn't require headless
Core Conceptsโ
What Mock Mode Doesโ
When mock mode is enabled (via brobot.mock=true or brobot.core.mock=true property, or programmatically with MockModeManager.setMockMode(true)):
- No screen capture - Brobot doesn't capture actual screens
- No real pattern matching - Image patterns aren't matched against real screens
- Probabilistic simulation - States and patterns are "found" based on configured probabilities
- State-based testing - Focus on testing state transitions and automation logic
State Probabilitiesโ
State probabilities determine how often a state's objects (images, regions, etc.) are "found" during mock execution:
- 100% probability: State objects are always found (deterministic testing)
- 0% probability: State objects are never found (failure testing)
- 1-99% probability: Stochastic testing for robustness
Configurationโ
Enabling Mock Modeโ
Property-Based Configuration (Recommended)โ
Brobot uses simplified mock configuration properties:
# application.properties
# Enable mock mode (simulated actions)
brobot.mock=true
# Probability of action success (0.0 to 1.0, default 1.0)
brobot.mock.action.success.probability=0.95
# Headless configuration (if no display available)
brobot.headless=false # Set to true for CI/CD environments
brobot.headless.debug=false # Enable for headless detection debugging
Note: The brobot.headless property must be explicitly set. Auto-detection has been removed due to reliability issues on Windows systems.
Property System Clarification: Brobot supports two property forms for mock mode:
brobot.mock=true- Simplified system property (managed by MockModeManager)brobot.core.mock=true- Spring Boot configuration property (mapped to BrobotProperties)
Both forms are valid and synchronized automatically. Use whichever fits your configuration style.
Programmatic Configurationโ
// Note: BrobotProperties must be injected as a dependency
@Autowired
private BrobotProperties brobotProperties;
import io.github.jspinak.brobot.config.mock.MockModeManager;
// Enable mock mode globally
MockModeManager.setMockMode(true);
// Check if mock mode is enabled
if (brobotProperties.getCore().isMock()) {
// Mock-specific logic
}
// Log current mock mode state across all components
MockModeManager.logMockModeState();
The MockModeManager automatically synchronizes mock mode across:
- System properties (
brobot.mock) ExecutionEnvironment(for runtime behavior)brobotProperties.getCore().isMock()(for compatibility)
Action Success Probabilityโ
The brobot.mock.action.success.probability property controls how often simulated actions succeed:
- 1.0 (default): All actions always succeed - ideal for deterministic testing
- 0.95: 95% success rate - simulates realistic conditions
- 0.5: 50% success rate - stress testing
- 0.0: All actions always fail - failure path testing
This applies to actions like click, type, and drag. Find operations still require ActionSnapshots for proper match simulation.
Setting State Probabilitiesโ
There are two approaches to configure state probabilities:
1. State-Level Configuration (Recommended)โ
Configure probabilities directly in state classes:
package com.yourapp.states;
import io.github.jspinak.brobot.annotations.State;
import io.github.jspinak.brobot.config.core.BrobotProperties;
import io.github.jspinak.brobot.datastructures.state.stateobject.StateImage;
import io.github.jspinak.brobot.tools.testing.mock.state.MockStateManagement;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@State(initial = true)
@Component
@Getter
@Slf4j
public class LoginState {
@Autowired(required = false)
private MockStateManagement mockStateManagement;
@Autowired
private BrobotProperties brobotProperties;
// Define mock probability for this state
private static final int MOCK_PROBABILITY = 100;
private final StateImage loginButton;
public LoginState() {
loginButton = new StateImage.Builder()
.addPatterns("login-button")
.setName("LoginButton")
.build();
}
@PostConstruct
public void configureMockProbability() {
if (brobotProperties.getCore().isMock() && mockStateManagement != null) {
mockStateManagement.setStateProbabilities(MOCK_PROBABILITY, "Login");
log.debug("Configured Login state mock probability to {}%", MOCK_PROBABILITY);
}
}
}
2. Centralized Configurationโ
Use MockStateManagement to configure multiple states:
@Configuration
@ConditionalOnProperty(name = "brobot.mock", havingValue = "true")
public class MockConfiguration {
@Autowired
private MockStateManagement mockStateManagement;
@PostConstruct
public void configureMockStates() {
// Set initial state probabilities
mockStateManagement.setStateProbabilities(100, "Login"); // Always found
mockStateManagement.setStateProbabilities(0, "Dashboard"); // Initially not found
mockStateManagement.setStateProbabilities(50, "ErrorDialog"); // Sometimes found
}
}
Testing State Transitionsโ
Deterministic Flow Testingโ
For testing automation flow (like claude-automator), use 100% probabilities to ensure reliable transitions:
@State(initial = true) // Mark as initial state
public class PromptState {
private static final int MOCK_PROBABILITY = 100; // Always found
// ... state definition
}
@State // Not initial - activated through transition
public class WorkingState {
private static final int MOCK_PROBABILITY = 100; // Always found when active
// ... state definition
}
This ensures:
- Transitions always succeed when triggered
- Focus on testing the automation logic, not robustness
- Predictable test outcomes
Stochastic Testingโ
For robustness testing, use variable probabilities:
// Simulate unreliable GUI element detection
mockStateManagement.setStateProbabilities(70, "UnstableDialog");
// Test retry logic
for (int i = 0; i < MAX_RETRIES; i++) {
ActionResult result = action.find(dialogElement);
if (result.isSuccess()) break;
Thread.sleep(1000);
}
Dynamic State Simulationโ
Simulating State Changesโ
Adjust probabilities during test execution to simulate state transitions:
@Test
public void testLoginFlow() {
// Initial state: Login visible, Dashboard not
mockStateManagement.setStateProbabilities(100, "Login");
mockStateManagement.setStateProbabilities(0, "Dashboard");
// Perform login action
stateNavigator.openState("Dashboard");
// Simulate successful login: Dashboard appears, Login disappears
mockStateManagement.setStateProbabilities(0, "Login");
mockStateManagement.setStateProbabilities(100, "Dashboard");
// Verify transition
assertTrue(stateMemory.getActiveStateNames().contains("Dashboard"));
}
Simulating Temporal Behaviorsโ
public void simulateLoadingSequence() {
// Loading appears
mockStateManagement.setStateProbabilities(100, "LoadingSpinner");
// Simulate loading time
Thread.sleep(2000);
// Loading disappears, content appears
mockStateManagement.setStateProbabilities(0, "LoadingSpinner");
mockStateManagement.setStateProbabilities(100, "ContentLoaded");
}
Best Practicesโ
1. Use 100% Probability for Flow Testingโ
When testing automation logic (not robustness):
// All states should be reliably findable
private static final int MOCK_PROBABILITY = 100;
2. Set Initial States Appropriatelyโ
@State(initial = true) // Only the starting state(s)
public class InitialState { }
@State // Subsequent states reached through transitions
public class SubsequentState { }
3. Document Mock Behaviorโ
/**
* Login state - always visible at application start.
* Mock probability: 100% (deterministic for flow testing)
*/
@State(initial = true)
public class LoginState { }
4. Separate Mock Configurationโ
Keep mock-specific configuration separate:
# application.properties
brobot.core.mock=false # Production
# application-test.properties
brobot.core.mock=true # Testing
5. Clean State Between Testsโ
@AfterEach
public void cleanup() {
stateMemory.getActiveStates().clear();
// Reset probabilities if needed
}
Testing Patternsโ
Pattern 1: Simple Flow Testโ
@Test
public void testBasicFlow() {
// All states 100% for deterministic testing
mockStateManagement.setStateProbabilities(100, "Start", "Middle", "End");
// Test the flow
assertTrue(stateNavigator.openState("Middle"));
assertTrue(stateNavigator.openState("End"));
}
Pattern 2: Error Recovery Testโ
@Test
public void testErrorRecovery() {
// Normal states always found
mockStateManagement.setStateProbabilities(100, "Normal");
// Error appears intermittently
mockStateManagement.setStateProbabilities(30, "Error");
// Test should handle both cases
ActionResult result = action.find(element);
if (!result.isSuccess()) {
// Handle error case
handleError();
}
}
Pattern 3: State Verificationโ
@Autowired
private InitialStates initialStates;
@Autowired
private StateService stateService;
@Test
public void verifyStateConfiguration() {
// Verify initial states are registered
assertTrue(initialStates.hasRegisteredInitialStates());
var initialStateNames = initialStates.getRegisteredInitialStates();
assertEquals(1, initialStateNames.size());
assertEquals("Login", initialStateNames.get(0));
// Verify all states registered
assertTrue(stateService.getAllStates().stream()
.anyMatch(s -> s.getName().equals("Dashboard")));
}
Debugging Mock Testsโ
Enable Verbose Loggingโ
logging.level.io.github.jspinak.brobot.tools.testing.mock=DEBUG
logging.level.com.yourapp.states=DEBUG
Log State Transitionsโ
@EventListener
public void handleStateTransition(StateTransitionEvent event) {
log.info("Transition: {} -> {}",
event.getFromState(), event.getToState());
}
Verify Mock Configurationโ
@Test
public void verifyMockSetup() {
assertTrue(brobotProperties.getCore().isMock(), "Mock mode should be enabled");
assertNotNull(mockStateManagement, "MockStateManagement should be available");
}
Common Issues and Solutionsโ
Issue: States Not Being Foundโ
Solution: Verify probability is set > 0:
mockStateManagement.setStateProbabilities(100, "StateName");
Issue: Wrong Initial Stateโ
Solution: Ensure only one state has initial = true:
@State(initial = true) // Only one state should have this
Issue: Transitions Not Workingโ
Solution: Check state registration and transition definitions. Use the correct transition format:
@TransitionSet(state = SourceState.class) // Source state for these transitions
@Component
@RequiredArgsConstructor
public class SourceStateTransitions {
private final SourceState sourceState;
private final Action action;
private final BrobotProperties brobotProperties;
/**
* Navigate FROM SourceState TO TargetState
*/
@OutgoingTransition(activate = {TargetState.class}, pathCost = 1)
public boolean toTargetState() {
if (brobotProperties.getCore().isMock()) return true;
return action.click(sourceState.getButton()).isSuccess();
}
/**
* Verify arrival AT SourceState
*/
@IncomingTransition
public boolean verifyArrival() {
if (brobotProperties.getCore().isMock()) return true;
return action.find(sourceState.getElement()).isSuccess();
}
}
Issue: Mock Mode Not Activatingโ
Solution: Verify configuration:
brobot.core.mock=true
Enhanced Mock Infrastructureโ
Grid Operations Supportโ
Mock mode now provides full support for grid operations without requiring SikuliX:
import io.github.jspinak.brobot.tools.testing.mock.grid.MockGridConfig;
@Test
public void testGridNavigation() {
// Configure grid for testing
MockGridConfig.setDefaultGrid(3, 3); // 3x3 grid
Region screen = new Region(0, 0, 900, 900);
// Test grid navigation
for (int i = 0; i < 9; i++) {
Region gridCell = screen.getGridRegion(i);
assertNotNull(gridCell);
assertEquals(300, gridCell.w());
assertEquals(300, gridCell.h());
}
// Test location to grid mapping
Location centerOfTopRight = new Location(750, 150);
Optional<Integer> gridNum = RegionUtils.getGridNumber(screen, centerOfTopRight);
assertTrue(gridNum.isPresent());
assertEquals(2, gridNum.get()); // Top-right is index 2 in 3x3 grid
}
Scene and Color Analysis Mockingโ
The MockSceneBuilder provides comprehensive test data for color-based operations:
import io.github.jspinak.brobot.tools.testing.mock.builders.MockSceneBuilder;
@Test
public void testColorMatching() {
// Create mock scene with proper image initialization
Scene scene = MockSceneBuilder.createMockScene();
// Create scene analysis with color profiles
SceneAnalysis analysis = MockSceneBuilder.sceneAnalysis()
.withPixelProfile(0)
.withPixelProfile(1)
.build();
// Color operations work in mock mode
ColorClassifier classifier = new ColorClassifier();
Mat result = classifier.getImageIndices(analysis, ColorCluster.ColorSchemaName.BGR);
assertNotNull(result);
}
Test Base Class - BrobotTestBaseโ
All tests should extend BrobotTestBase for proper mock configuration:
import io.github.jspinak.brobot.test.BrobotTestBase;
public class MyAutomationTest extends BrobotTestBase {
@Test
public void testWithMockMode() {
// Mock mode is automatically enabled
// No headless exceptions
// Fast execution times
ActionResult result = action.find(targetElement);
assertTrue(result.isSuccess());
}
}
Key benefits of BrobotTestBase:
- Automatic mock mode activation
- CI/CD pipeline compatibility
- Fast operation timings (0.01-0.04s)
- No display server required
- Consistent test environment
Performance Benefitsโ
Mock mode operations are significantly faster:
| Operation | Mock Mode | Real Mode | Speedup |
|---|---|---|---|
| Find operation | ~0.01s | 0.5-2s | 50-200x |
| Grid calculation | ~0.01s | 0.5s | 50x |
| Color analysis | ~0.02s | 1-2s | 50-100x |
| State transition | ~0.01s | 0.2-1s | 20-100x |
Common Pitfalls and Solutionsโ
| Issue | Solution |
|---|---|
| Tests fail in CI/CD | Extend BrobotTestBase |
| Grid operations return empty | Configure MockGridConfig.setDefaultGrid() |
| Color tests throw NPE | Use MockSceneBuilder for test data |
| SikuliX mocking errors | Use real SikuliX objects or Brobot mocks |
| Inconsistent test results | Ensure mock mode is enabled in setup |
Summaryโ
Mock mode in Brobot enables:
- Deterministic testing with 100% probabilities for flow validation
- Stochastic testing with variable probabilities for robustness
- CI/CD integration without GUI dependencies
- Rapid development without target application availability
- Grid operations without SikuliX dependency
- Color analysis without real images
- 50-200x faster test execution
Choose probability settings based on your testing goals:
- 100% for automation flow testing
- Variable for robustness and error handling
- Dynamic for simulating complex scenarios
Use the enhanced mock infrastructure for:
- Grid-based navigation testing
- Color matching validation
- Headless environment compatibility
- Fast CI/CD pipeline execution
See Alsoโ
Essential Testing Documentationโ
- Testing Introduction - Overview of Brobot testing approaches
- Mock Mode Manager - Centralized mock mode management
- Test Utilities - BrobotTestBase and testing utilities
- Unit Testing - Unit testing patterns and best practices
- Integration Testing - Integration testing guide
- Profile-Based Testing - Spring profiles for testing
- Mat Testing Utilities - OpenCV Mat testing utilities
Mock Mode Ecosystemโ
- Mock Stochasticity - Probabilistic testing and state probabilities
- Mock Mode Migration - Migrating to MockModeManager
- ActionHistory Mock Snapshots - Creating mock data with ActionHistory
- ActionHistory Integration Testing - Testing with action histories
- Testing Strategy - Overall testing strategy
State and Transition Documentationโ
- States - Introduction to Brobot states
- Transitions - State transition fundamentals
- Initial States Configuration - Configuring initial states
Configurationโ
- BrobotProperties Usage - Configuration guide
- Properties Reference - All available properties
- Headless Configuration - Headless environment setup
Tutorialsโ
- Mock Results Tutorial - Working with mock results
- Tutorial Basics - States - State basics tutorial
- Tutorial Basics - Transitions - Transition basics tutorial