Testing Strategies
This guide explains testing strategies and best practices for TrustWeave applications and plugins.
Overview
TrustWeave provides comprehensive testing utilities and strategies for:
- Unit Testing – testing individual components in isolation
- Integration Testing – testing component interactions
- End-to-End Testing – testing complete workflows
- Mock Testing – using in-memory implementations
Testing Utilities
trustweave-testkit
The trustweave-testkit module provides in-memory implementations:
InMemoryKeyManagementService– in-memory KMS for testingInMemoryBlockchainAnchorClient– in-memory blockchain client for testingDidKeyMockMethod– mock DID method implementationTrustWeaveTestFixture– comprehensive test fixture builder
1
2
3
dependencies {
testImplementation("com.trustweave:trustweave-testkit:1.0.0-SNAPSHOT")
}
Unit Testing
Testing DID Methods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.trustweave.testkit.*
import com.trustweave.did.*
import kotlin.test.Test
import kotlin.test.assertNotNull
class DidMethodTest {
@Test
fun testCreateDid() = runBlocking {
val kms = InMemoryKeyManagementService()
val method = DidKeyMockMethod(kms)
val options = didCreationOptions {
algorithm = KeyAlgorithm.Ed25519
}
val did = method.createDid(options)
assertNotNull(did)
assert(did.id.startsWith("did:key:"))
}
}
What this does: Tests DID creation in isolation using in-memory KMS.
Outcome: Fast, reliable unit tests without external dependencies.
Testing Key Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.trustweave.testkit.kms.InMemoryKeyManagementService
import com.trustweave.kms.*
import kotlin.test.Test
import kotlin.test.assertEquals
class KmsTest {
@Test
fun testGenerateAndSign() = runBlocking {
val kms = InMemoryKeyManagementService()
val key = kms.generateKey(Algorithm.Ed25519)
assertNotNull(key)
val data = "Hello, TrustWeave!".toByteArray()
val signature = kms.sign(key.id, data)
assertNotNull(signature)
assertEquals(64, signature.size) // Ed25519 signature size
}
}
Outcome: Tests key generation and signing without external KMS.
Integration Testing
Testing Credential Workflows
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import com.trustweave.testkit.*
import com.trustweave.TrustWeave
import com.trustweave.did.*
import kotlin.test.Test
class CredentialWorkflowTest {
@Test
fun testCredentialIssuanceAndVerification() = runBlocking {
val fixture = TrustWeaveTestFixture.builder()
.withInMemoryBlockchainClient("algorand:testnet")
.build()
.use { fixture ->
val TrustWeave = TrustWeave.create()
// Create issuer DID
val issuerDid = TrustWeave.dids.create()
// Issue credential
val credential = TrustWeave.issueCredential(
issuerDid = issuerDid.id,
issuerKeyId = issuerDid.document.verificationMethod.first().id,
credentialSubject = buildJsonObject {
put("id", "did:key:subject")
put("name", "Alice")
}
).getOrThrow()
// Verify credential
val verificationResult = TrustWeave.verifyCredential(credential).getOrThrow()
assert(verificationResult.valid)
}
}
}
Outcome: Tests complete credential issuance and verification workflows.
Testing Blockchain Anchoring
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import com.trustweave.anchor.*
import kotlin.test.Test
import kotlin.test.assertEquals
class AnchoringTest {
@Test
fun testAnchorAndRead() = runBlocking {
val client = InMemoryBlockchainAnchorClient("algorand:testnet")
val payload = "Hello, TrustWeave!".toByteArray()
val result = client.writePayload(payload).getOrThrow()
val readData = client.readPayload(result.anchorRef).getOrThrow()
assertEquals(payload.toList(), readData.toList())
}
}
Outcome: Tests blockchain anchoring without actual blockchain connections.
End-to-End Testing
EO Integration Tests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import com.trustweave.testkit.eo.BaseEoIntegrationTest
import com.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import com.trustweave.anchor.*
import kotlin.test.Test
class MyEoIntegrationTest : BaseEoIntegrationTest() {
override fun createAnchorClient(
chainId: String,
options: Map<String, Any?>
): BlockchainAnchorClient {
return InMemoryBlockchainAnchorClient(chainId)
}
@Test
fun testEoScenario() = runBlocking {
val result = runEoTestScenario()
assert(result.verificationResult.valid)
}
}
Outcome: Tests complete EO workflows with automatic setup and teardown.
Test Fixtures
Using TrustWeaveTestFixture
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.trustweave.testkit.*
import kotlin.test.Test
class FixtureTest {
@Test
fun testWithFixture() = runBlocking {
val fixture = TrustWeaveTestFixture.builder()
.withKms(InMemoryKeyManagementService())
.withDidMethod("key") { DidKeyMockMethod(it) }
.withBlockchainClient("algorand:testnet") {
InMemoryBlockchainAnchorClient("algorand:testnet")
}
.build()
.use { fixture ->
val issuerDoc = fixture.createIssuerDid()
assertNotNull(issuerDoc)
val client = fixture.getBlockchainClient("algorand:testnet")
assertNotNull(client)
}
}
}
Outcome: Provides comprehensive test environment setup with automatic cleanup.
Best Practices
Isolation
Keep tests isolated:
1
2
3
4
5
6
7
@Test
fun testIsolated() = runBlocking {
// Each test gets its own fixture
val fixture = TrustWeaveTestFixture.builder().build().use { fixture ->
// Test code
}
}
Resource Cleanup
Use use {} for automatic cleanup:
1
2
3
4
fixture.use { fixture ->
// Test code
// Automatic cleanup on exit
}
Error Testing
Test error cases:
1
2
3
4
5
6
7
8
9
10
11
12
@Test
fun testErrorHandling() = runBlocking {
val kms = InMemoryKeyManagementService()
val result = kms.sign("nonexistent-key", "data".toByteArray())
result.fold(
onSuccess = { fail("Expected error") },
onFailure = { error ->
assert(error is TrustWeaveError.KeyNotFound)
}
)
}
Performance Testing
Test performance-critical paths:
1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
fun testPerformance() = runBlocking {
val kms = InMemoryKeyManagementService()
val start = System.currentTimeMillis()
repeat(1000) {
kms.generateKey(Algorithm.Ed25519)
}
val duration = System.currentTimeMillis() - start
assert(duration < 1000) // Should complete in under 1 second
}
Testing Plugins
Testing Custom DID Methods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.trustweave.testkit.*
import com.trustweave.did.*
import kotlin.test.Test
class MyCustomDidMethodTest {
@Test
fun testCreateAndResolve() = runBlocking {
val kms = InMemoryKeyManagementService()
val config = MyDidConfig.default()
val method = MyCustomDidMethod(kms, config)
// Create DID
val did = method.createDid(didCreationOptions {
algorithm = KeyAlgorithm.Ed25519
})
// Resolve DID
val resolutionResult = method.resolveDid(did.id)
assertNotNull(resolutionResult.didDocument)
assertEquals(did.id, resolutionResult.didDocument?.id)
}
}
Testing Custom Blockchain Adapters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import com.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import com.trustweave.anchor.*
import kotlin.test.Test
class MyBlockchainAdapterTest {
@Test
fun testAnchor() = runBlocking {
val config = MyBlockchainConfig.testnet()
val client = MyBlockchainAnchorClient("myblockchain:testnet", config)
val payload = "test".toByteArray()
val result = client.writePayload(payload).getOrThrow()
assertNotNull(result.anchorRef.transactionHash)
}
}
Test Coverage
Measuring Coverage
Use coverage tools to measure test coverage:
1
./gradlew test jacocoTestReport
Target Coverage
Aim for:
- Unit Tests – 80%+ coverage
- Integration Tests – cover critical paths
- End-to-End Tests – cover main workflows
Next Steps
- Review trustweave-testkit Module for testing utilities
- See Error Handling for error testing patterns
- Check Creating Plugins for plugin testing
- Explore existing tests in TrustWeave modules for examples