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 testing
  • InMemoryBlockchainAnchorClient – in-memory blockchain client for testing
  • DidKeyMockMethod – mock DID method implementation
  • TrustWeaveTestFixture – comprehensive test fixture builder
1
2
3
dependencies {
    testImplementation("org.trustweave:testkit:0.6.0")
}

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 org.trustweave.testkit.*
import org.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 org.trustweave.testkit.kms.InMemoryKeyManagementService
import org.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
34
import kotlinx.coroutines.runBlocking
import org.trustweave.credential.results.VerificationResult
import org.trustweave.testkit.services.*
import org.trustweave.trust.TrustWeave
import org.trustweave.trust.dsl.credential.*
import org.trustweave.trust.types.getOrThrow
import org.trustweave.credential.results.getOrThrow
import org.trustweave.trust.types.getOrThrowDid
import kotlin.test.Test
import kotlin.test.assertTrue

class CredentialWorkflowTest {
    @Test
    fun testCredentialIssuanceAndVerification() = runBlocking {
        val trustWeave = TrustWeave.build {
            keys { provider(IN_MEMORY); algorithm(ED25519) }
            did { method(KEY) { algorithm(ED25519) } }
        }
        val issuerDid = trustWeave.createDid { }.getOrThrowDid()
        val credential = trustWeave.issue {
            credential {
                type("VerifiableCredential", "PersonCredential")
                issuer(issuerDid)
                subject {
                    id("did:key:subject")
                    "name" to "Alice"
                }
            }
            signedBy(issuerDid, "key-1")
        }.getOrThrow()
        val verification = trustWeave.verify(credential)
        assertTrue(verification is VerificationResult.Valid, verification.toString())
    }
}

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
18
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.JsonPrimitive
import org.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import kotlin.test.Test
import kotlin.test.assertEquals

class AnchoringTest {
    @Test
    fun testAnchorAndRead() = runBlocking {
        val client = InMemoryBlockchainAnchorClient("algorand:testnet")
        val payload = JsonPrimitive("Hello, TrustWeave!")

        val anchored = client.writePayload(payload, "application/json")
        val readBack = client.readPayload(anchored.ref)

        assertEquals(payload, readBack.payload)
    }
}

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
20
import org.trustweave.credential.results.VerificationResult
import org.trustweave.testkit.eo.BaseEoIntegrationTest
import org.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import org.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 is 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
23
import org.trustweave.testkit.*
import kotlin.test.Test
import org.trustweave.testkit.services.*

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 TrustWeaveException.NotFound)
        }
    )
}

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
23
24
25
26
import org.trustweave.testkit.*
import org.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)
        val resolved = when (resolutionResult) {
            is DidResolutionResult.Success -> resolutionResult.document
            else -> null
        }
        assertNotNull(resolved)
        assertEquals(did.id, resolved?.id)
    }
}

Testing custom blockchain adapters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.JsonPrimitive
import org.trustweave.testkit.anchor.InMemoryBlockchainAnchorClient
import kotlin.test.Test
import kotlin.test.assertTrue

class MyBlockchainAdapterTest {
    @Test
    fun testAnchor() = runBlocking {
        val client = InMemoryBlockchainAnchorClient("myblockchain:testnet")
        val anchored = client.writePayload(JsonPrimitive("test"), "application/json")
        assertTrue(anchored.ref.txHash.isNotEmpty())
    }
}

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

References

  • TrustWeave-testkit Module](../modules/trustweave-testkit.md)
  • Error Handling](error-handling.md)
  • Creating Plugins](../contributing/creating-plugins.md)

This site uses Just the Docs, a documentation theme for Jekyll.