Writing Tests Guide
This guide explains how to write tests for TrustWeave plugins and components.
Test Structure
Unit Tests
Use BasePluginTest for unit tests:
1
2
3
4
5
6
7
8
9
10
11
12
13
import com.trustweave.testkit.BasePluginTest
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
import kotlin.test.assertNotNull
class MyPluginTest : BasePluginTest() {
@Test
fun testSomething() = runBlocking {
val fixture = createFixture()
// Test code
}
}
Integration Tests
Use BaseIntegrationTest for integration tests:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import com.trustweave.testkit.BaseIntegrationTest
import org.junit.jupiter.api.Tag
import org.testcontainers.junit.jupiter.Testcontainers
@Testcontainers
@Tag("integration")
class MyIntegrationTest : BaseIntegrationTest() {
@Test
fun testWithRealService() = runBlocking {
val fixture = createFixture()
// Integration test code
}
}
Test Templates
Use the provided templates as starting points:
Plugin Test Templates
- DID Methods:
docs/contributing/test-templates/DidMethodTestTemplate.kt - KMS Plugins:
docs/contributing/test-templates/KmsPluginTestTemplate.kt - Chain Plugins:
docs/contributing/test-templates/ChainPluginTestTemplate.kt
Trust Layer Integration Test Templates
Comprehensive in-memory workflow templates for trust layer integration tests:
- Location:
core/TrustWeave-trust/src/test/kotlin/com/geoknoesis/TrustWeave/integration/InMemoryTrustLayerIntegrationTest.kt - Templates Available:
- Complete in-memory workflow
- Credential revocation workflow
- Wallet storage workflow
- Verifiable presentation workflow
- DID update workflow
- Blockchain anchoring workflow
- Smart contract workflow
- External services template
See Trust Layer Test Templates for detailed documentation and examples.
Test Checklist
For each plugin, ensure tests cover:
- ✅ Happy Path: Successful operations
- ✅ Error Handling: Invalid inputs, network errors
- ✅ Edge Cases: Null values, empty collections, boundary values
- ✅ Algorithm Variations: Different algorithms/configurations
- ✅ SPI Discovery: Automatic plugin discovery (if applicable)
- ✅ Interface Compliance: All interface methods tested
Test Naming
Use descriptive test names:
1
2
3
4
5
6
7
8
9
@Test
fun `test create DID with Ed25519 algorithm`() = runBlocking {
// Test code
}
@Test
fun `test resolve non-existent DID returns error`() = runBlocking {
// Test code
}
Test Organization
Organize tests by functionality:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyPluginTest : BasePluginTest() {
@Test
fun testCreate() = runBlocking { }
@Test
fun testRead() = runBlocking { }
@Test
fun testUpdate() = runBlocking { }
@Test
fun testDelete() = runBlocking { }
}
Using Test Fixtures
1
2
3
4
5
6
7
8
9
10
11
12
class MyTest : BasePluginTest() {
@Test
fun testWithCustomFixture() = runBlocking {
withFixture({
withDidMethodPlugin("key")
withKmsPlugin("aws", mapOf("region" to "us-east-1"))
}) { fixture ->
// Test code
}
}
}
Best Practices
- Test Isolation: Each test should be independent
- Cleanup: Use
use {}pattern for automatic cleanup - Assertions: Use descriptive assertion messages
- Error Testing: Test both success and failure cases
- Coverage: Aim for 80%+ line coverage
Next Steps
- Trust Layer Test Templates - Comprehensive workflow templates
- Test Patterns - Common test patterns and examples
- Integration Testing - Integration test best practices
- Plugin Credential Handling - Handling external service credentials