Bridge Service Tests
This directory contains comprehensive tests for the bridge service located at cmd/bridge/main.go.
Test Structure
tests/bridge/
├── bridge_test.go # Core bridge functions extracted for testing
├── mqtt_handler_test.go # Unit tests for MQTT message handling
├── event_loop_test.go # Unit tests for event loop logic
├── integration_test.go # Integration tests with real Kafka
├── testutil.go # Test utilities and helper functions
└── README.md # This file
Test Categories
1. Unit Tests (mqtt_handler_test.go)
Tests the MQTT handler function that processes incoming beacon readings:
- TestMQTTHandler_SingleReading: Tests handling of a single beacon reading
- TestMQTTHandler_MultipleReadings: Tests handling of multiple readings in one message
- TestMQTTHandler_GatewayTypeSkipped: Verifies Gateway-type readings are filtered out
- TestMQTTHandler_UnknownBeaconSkipped: Verifies unknown beacons are skipped
- TestMQTTHandler_InvalidJSON: Tests error handling for invalid JSON
- TestMQTTHandler_HostnameExtraction: Tests hostname extraction from various topic formats
- TestMQTTHandler_PreservesRawData: Verifies raw data is preserved correctly
2. Event Loop Tests (event_loop_test.go)
Tests the main event loop logic:
- TestEventLoop_ApiUpdate_POST: Tests adding beacons via POST message
- TestEventLoop_ApiUpdate_DELETE: Tests removing beacons via DELETE message
- TestEventLoop_ApiUpdate_DELETE_All: Tests clearing all beacons
- TestEventLoop_AlertMessage: Tests alert message handling and MQTT publishing
- TestEventLoop_TrackerMessage: Tests tracker message handling and MQTT publishing
- TestEventLoop_ContextCancellation: Tests graceful shutdown on context cancellation
3. Integration Tests (integration_test.go)
End-to-end tests that interact with real Kafka infrastructure:
- TestIntegration_EndToEnd: Tests complete flow from MQTT message to Kafka
- TestIntegration_MultipleMessages: Tests handling multiple sequential messages
- TestIntegration_AppStateConcurrency: Tests concurrent access to AppState
- TestIntegration_CleanLookup: Tests the CleanLookup functionality
Running Tests
Run All Tests
go test ./tests/bridge/...
Run Only Unit Tests (skip integration tests)
go test ./tests/bridge/... -short
Run with Verbose Output
go test ./tests/bridge/... -v
Run Specific Test
go test ./tests/bridge/... -run TestMQTTHandler_SingleReading
Run with Coverage
go test ./tests/bridge/... -cover
Generate Coverage Report
go test ./tests/bridge/... -coverprofile=coverage.out
go tool cover -html=coverage.out
Integration Test Prerequisites
Integration tests require a running Kafka instance. By default, they connect to localhost:9092.
Running Kafka with Docker
docker run -d \
--name kafka-test \
-p 9092:9092 \
-e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 \
-e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
confluentinc/cp-kafka:latest
Custom Kafka URL
Set the KAFKA_URL environment variable:
KAFKA_URL=your-kafka-broker:9092 go test ./tests/bridge/...
Test Utilities
The testutil.go file provides helper functions:
NewTestHelper(t): Creates a test helper instance
CreateRawReading(mac, rssi): Creates test beacon readings
GenerateTestMAC(index): Generates test MAC addresses
SetupTestBeacons(appState): Sets up standard test beacons
AssertKafkaMessageCount(t, writer, expected): Asserts Kafka message count
Mocks
MockKafkaWriter
A mock implementation of the Kafka writer for unit tests that captures all messages written to it:
mockWriter := &MockKafkaWriter{Messages: []kafka.Message{}}
// ... use in tests ...
if len(mockWriter.Messages) != expected {
t.Errorf("Expected %d messages, got %d", expected, len(mockWriter.Messages))
}
MockMQTTClient
A mock implementation of the MQTT client for testing event loop logic:
mockClient := NewMockMQTTClient()
// ... use in tests ...
if _, exists := mockClient.PublishedMessages["/alerts"]; !exists {
t.Error("Expected message to be published to /alerts topic")
}
Key Test Scenarios
Beacon Lookup Flow
- Beacon is added to lookup via POST message
- MQTT message arrives with beacon reading
- Handler checks if beacon exists in lookup
- If exists, reading is forwarded to Kafka
- If not, reading is skipped
Message Filtering
- Gateway-type readings are filtered out
- Unknown beacons (not in lookup) are skipped
- Invalid JSON is logged and ignored
Concurrent Access
- Multiple goroutines can safely access AppState
- Beacon additions/removals are thread-safe
- CleanLookup removes all entries atomically
Troubleshooting
Integration Tests Fail
- Ensure Kafka is running:
docker ps | grep kafka
- Check Kafka logs:
docker logs kafka-test
- Verify connectivity:
telnet localhost 9092
- Check topic creation permissions
Tests Time Out
- Increase timeout in test context
- Check Kafka broker responsiveness
- Verify network connectivity
Import Errors
- Ensure you’re in the project root directory
- Check that go.mod is up to date:
go mod tidy
- Verify module path is correct
Contributing
When adding new tests:
- Follow the existing naming convention:
Test<FunctionName>_<Scenario>
- Use table-driven tests for multiple similar cases
- Add comments explaining what is being tested
- Use test utilities where appropriate
- Ensure tests are independent and can run in parallel
Notes
- Unit tests mock all external dependencies (Kafka, MQTT)
- Integration tests require real Kafka but mock MQTT
- All tests clean up after themselves
- Tests can run in parallel (no shared state)
- Context cancellation is properly tested for graceful shutdown