Skip to content

Commit ac76894

Browse files
authored
Fix CodeTransform tests that don't actually validate anything (#4195)
When a test is run under `launch`, the test runner does not actually confirm that the assertions within succeed While `launch { ... }.await()` would work, `runTest` is a better option as it provides test-specific niceties, such as waiting for child coroutines to finish before reporting test status and automatically timing out children if blocked for too long
1 parent 9f28b68 commit ac76894

File tree

5 files changed

+59
-51
lines changed

5 files changed

+59
-51
lines changed

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClient.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class FeatureDevClient(private val project: Project) {
4848

4949
private fun streamingBearerClient() = connection().getConnectionSettings().awsClient<CodeWhispererStreamingAsyncClient>()
5050

51-
private val amazonQStreamingClient = AmazonQStreamingClient.getInstance(project)
51+
private val amazonQStreamingClient
52+
get() = AmazonQStreamingClient.getInstance(project)
5253

5354
fun createTaskAssistConversation(): CreateTaskAssistConversationResponse = bearerClient().createTaskAssistConversation(
5455
CreateTaskAssistConversationRequest.builder().build()

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/services/codemodernizer/client/GumbyClient.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class GumbyClient(private val project: Project) {
4343

4444
private fun bearerClient() = connection().getConnectionSettings().awsClient<CodeWhispererRuntimeClient>()
4545

46-
private val amazonQStreamingClient = AmazonQStreamingClient.getInstance(project)
46+
private val amazonQStreamingClient
47+
get() = AmazonQStreamingClient.getInstance(project)
4748

4849
fun createGumbyUploadUrl(sha256Checksum: String): CreateUploadUrlResponse {
4950
val request = CreateUploadUrlRequest.builder()
@@ -123,8 +124,7 @@ class GumbyClient(private val project: Project) {
123124
suspend fun downloadExportResultArchive(jobId: JobId): MutableList<ByteArray> = amazonQStreamingClient.exportResultArchive(
124125
jobId.id,
125126
ExportIntent.TRANSFORMATION,
126-
{
127-
e ->
127+
{ e ->
128128
LOG.error(e) { "${CodeTransformApiNames.ExportResultArchive} failed: ${e.message}" }
129129
CodetransformTelemetry.logApiError(
130130
codeTransformApiNames = CodeTransformApiNames.ExportResultArchive,

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/amazonq/clients/AmazonQStreamingClientTest.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.amazonq.clients
55

66
import com.intellij.testFramework.RuleChain
77
import com.intellij.testFramework.replaceService
8-
import kotlinx.coroutines.launch
8+
import kotlinx.coroutines.test.runTest
99
import org.junit.Before
1010
import org.junit.Rule
1111
import org.junit.Test
12-
import org.mockito.ArgumentCaptor
1312
import org.mockito.kotlin.any
1413
import org.mockito.kotlin.argumentCaptor
1514
import org.mockito.kotlin.doReturn
@@ -25,7 +24,6 @@ import software.amazon.awssdk.services.ssooidc.SsoOidcClient
2524
import software.aws.toolkits.core.TokenConnectionSettings
2625
import software.aws.toolkits.core.utils.test.aString
2726
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
28-
import software.aws.toolkits.jetbrains.core.coroutines.projectCoroutineScope
2927
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
3028
import software.aws.toolkits.jetbrains.core.credentials.ManagedSsoProfile
3129
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
@@ -57,7 +55,9 @@ class AmazonQStreamingClientTest : AmazonQTestBase() {
5755
ssoClient = mockClientManagerRule.create()
5856

5957
streamingBearerClient = mockClientManagerRule.create<CodeWhispererStreamingAsyncClient>().stub {
60-
on { exportResultArchive(any<ExportResultArchiveRequest>(), any<ExportResultArchiveResponseHandler>()) } doReturn CompletableFuture()
58+
on {
59+
exportResultArchive(any<ExportResultArchiveRequest>(), any<ExportResultArchiveResponseHandler>())
60+
} doReturn CompletableFuture.completedFuture(mock()) // void type can't be instantiated
6161
}
6262

6363
val mockConnection = mock<AwsBearerTokenConnection>()
@@ -73,15 +73,13 @@ class AmazonQStreamingClientTest : AmazonQTestBase() {
7373
}
7474

7575
@Test
76-
fun `check exportResultArchive`() {
77-
val requestCaptor = ArgumentCaptor.forClass(ExportResultArchiveRequest::class.java)
78-
val handlerCaptor = ArgumentCaptor.forClass(ExportResultArchiveResponseHandler::class.java)
76+
fun `check exportResultArchive`() = runTest {
77+
val requestCaptor = argumentCaptor<ExportResultArchiveRequest>()
78+
val handlerCaptor = argumentCaptor<ExportResultArchiveResponseHandler>()
7979

80-
projectCoroutineScope(project).launch {
81-
amazonQStreamingClient.exportResultArchive("test-id", ExportIntent.TRANSFORMATION, {}, {})
82-
argumentCaptor<ExportResultArchiveRequest, ExportResultArchiveResponseHandler>().apply {
83-
verify(streamingBearerClient).exportResultArchive(requestCaptor.capture(), handlerCaptor.capture())
84-
}
80+
amazonQStreamingClient.exportResultArchive("test-id", ExportIntent.TRANSFORMATION, {}, {})
81+
argumentCaptor<ExportResultArchiveRequest, ExportResultArchiveResponseHandler>().apply {
82+
verify(streamingBearerClient).exportResultArchive(requestCaptor.capture(), handlerCaptor.capture())
8583
}
8684
}
8785
}

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/amazonqFeatureDev/clients/FeatureDevClientTest.kt

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.amazonqFeatureDev
55

66
import com.intellij.testFramework.RuleChain
77
import com.intellij.testFramework.replaceService
8-
import kotlinx.coroutines.launch
8+
import kotlinx.coroutines.test.runTest
99
import org.assertj.core.api.Assertions.assertThat
1010
import org.junit.After
1111
import org.junit.Before
1212
import org.junit.Rule
1313
import org.junit.Test
14-
import org.mockito.ArgumentCaptor
1514
import org.mockito.kotlin.any
1615
import org.mockito.kotlin.argumentCaptor
1716
import org.mockito.kotlin.doReturn
17+
import org.mockito.kotlin.eq
1818
import org.mockito.kotlin.mock
1919
import org.mockito.kotlin.stub
2020
import org.mockito.kotlin.verify
2121
import org.mockito.kotlin.verifyNoInteractions
22+
import org.mockito.kotlin.verifyNoMoreInteractions
2223
import org.mockito.kotlin.whenever
2324
import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient
2425
import software.amazon.awssdk.services.codewhispererruntime.model.CreateTaskAssistConversationRequest
@@ -31,13 +32,14 @@ import software.amazon.awssdk.services.codewhispererruntime.model.StartTaskAssis
3132
import software.amazon.awssdk.services.codewhispererruntime.model.StartTaskAssistCodeGenerationResponse
3233
import software.amazon.awssdk.services.codewhispererstreaming.CodeWhispererStreamingAsyncClient
3334
import software.amazon.awssdk.services.codewhispererstreaming.model.ExportIntent
35+
import software.amazon.awssdk.services.codewhispererstreaming.model.ExportResultArchiveRequest
36+
import software.amazon.awssdk.services.codewhispererstreaming.model.ExportResultArchiveResponseHandler
3437
import software.amazon.awssdk.services.codewhispererstreaming.model.GenerateTaskAssistPlanRequest
3538
import software.amazon.awssdk.services.codewhispererstreaming.model.GenerateTaskAssistPlanResponseHandler
3639
import software.amazon.awssdk.services.ssooidc.SsoOidcClient
3740
import software.aws.toolkits.core.TokenConnectionSettings
3841
import software.aws.toolkits.core.utils.test.aString
3942
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
40-
import software.aws.toolkits.jetbrains.core.coroutines.projectCoroutineScope
4143
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
4244
import software.aws.toolkits.jetbrains.core.credentials.ManagedSsoProfile
4345
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
@@ -81,10 +83,17 @@ class FeatureDevClientTest : FeatureDevTestBase() {
8183
}
8284

8385
streamingBearerClient = mockClientManagerRule.create<CodeWhispererStreamingAsyncClient>().stub {
84-
on { generateTaskAssistPlan(any<GenerateTaskAssistPlanRequest>(), any<GenerateTaskAssistPlanResponseHandler>()) } doReturn CompletableFuture()
86+
on {
87+
generateTaskAssistPlan(any<GenerateTaskAssistPlanRequest>(), any<GenerateTaskAssistPlanResponseHandler>())
88+
} doReturn CompletableFuture.completedFuture(mock()) // void type can't be instantiated
89+
90+
on {
91+
exportResultArchive(any<ExportResultArchiveRequest>(), any<ExportResultArchiveResponseHandler>())
92+
} doReturn CompletableFuture.completedFuture(mock()) // void type can't be instantiated
8593
}
8694

8795
amazonQStreamingClient = mock<AmazonQStreamingClient>()
96+
projectRule.project.replaceService(AmazonQStreamingClient::class.java, amazonQStreamingClient, disposableRule.disposable)
8897

8998
val mockConnection = mock<AwsBearerTokenConnection>()
9099
whenever(mockConnection.getConnectionSettings()) doReturn mock<TokenConnectionSettings>()
@@ -132,31 +141,28 @@ class FeatureDevClientTest : FeatureDevTestBase() {
132141
}
133142

134143
@Test
135-
fun `check generateTaskAssistPlan`() {
136-
val requestCaptor = ArgumentCaptor.forClass(GenerateTaskAssistPlanRequest::class.java)
137-
val handlerCaptor = ArgumentCaptor.forClass(GenerateTaskAssistPlanResponseHandler::class.java)
138-
139-
projectCoroutineScope(project).launch {
140-
featureDevClient.generateTaskAssistPlan(testConversationId, "test-upload-id", "test-user-message")
141-
argumentCaptor<GenerateTaskAssistPlanRequest, GenerateTaskAssistPlanResponseHandler>().apply {
142-
verify(streamingBearerClient).generateTaskAssistPlan(requestCaptor.capture(), handlerCaptor.capture())
143-
verifyNoInteractions(bearerClient)
144-
}
144+
fun `check generateTaskAssistPlan`() = runTest {
145+
val requestCaptor = argumentCaptor<GenerateTaskAssistPlanRequest>()
146+
val handlerCaptor = argumentCaptor<GenerateTaskAssistPlanResponseHandler>()
147+
148+
featureDevClient.generateTaskAssistPlan(testConversationId, "test-upload-id", "test-user-message")
149+
argumentCaptor<GenerateTaskAssistPlanRequest, GenerateTaskAssistPlanResponseHandler>().apply {
150+
verify(streamingBearerClient).generateTaskAssistPlan(requestCaptor.capture(), handlerCaptor.capture())
151+
verifyNoInteractions(bearerClient)
145152
}
146153
}
147154

148155
@Test
149-
fun `check exportTaskAssistResultArchive`() {
150-
projectCoroutineScope(project).launch {
151-
whenever(amazonQStreamingClient.exportResultArchive(any<String>(), any<ExportIntent>(), any(), any())) doReturn exampleExportResultArchiveResponse
156+
fun `check exportTaskAssistResultArchive`() = runTest {
157+
whenever(amazonQStreamingClient.exportResultArchive(any<String>(), any<ExportIntent>(), any(), any())) doReturn exampleExportResultArchiveResponse
152158

153-
val actual = featureDevClient.exportTaskAssistResultArchive("1234")
159+
val actual = featureDevClient.exportTaskAssistResultArchive("1234")
154160

155-
verifyNoInteractions(bearerClient)
156-
verifyNoInteractions(streamingBearerClient)
157-
assertThat(actual).isInstanceOf(ByteArray::class.java)
158-
assertThat(actual).usingRecursiveComparison().isEqualTo(exampleExportResultArchiveResponse)
159-
}
161+
verify(amazonQStreamingClient).exportResultArchive(eq("1234"), eq(ExportIntent.TASK_ASSIST), any(), any())
162+
verifyNoInteractions(bearerClient)
163+
verifyNoInteractions(streamingBearerClient)
164+
verifyNoMoreInteractions(amazonQStreamingClient)
165+
assertThat(actual).usingRecursiveComparison().isEqualTo(exampleExportResultArchiveResponse)
160166
}
161167

162168
@Test

plugins/toolkit/jetbrains-core/tst/software/aws/toolkits/jetbrains/services/codewhisperer/codemodernizer/CodeWhispererCodeModernizerGumbyClientTest.kt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.codemodernizer
55

66
import com.intellij.testFramework.RuleChain
77
import com.intellij.testFramework.replaceService
8-
import kotlinx.coroutines.launch
8+
import kotlinx.coroutines.test.runTest
99
import org.assertj.core.api.Assertions.assertThat
1010
import org.junit.After
1111
import org.junit.Before
@@ -14,10 +14,12 @@ import org.junit.Test
1414
import org.mockito.kotlin.any
1515
import org.mockito.kotlin.argumentCaptor
1616
import org.mockito.kotlin.doReturn
17+
import org.mockito.kotlin.eq
1718
import org.mockito.kotlin.mock
1819
import org.mockito.kotlin.stub
1920
import org.mockito.kotlin.verify
2021
import org.mockito.kotlin.verifyNoInteractions
22+
import org.mockito.kotlin.verifyNoMoreInteractions
2123
import org.mockito.kotlin.whenever
2224
import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient
2325
import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUrlRequest
@@ -39,7 +41,6 @@ import software.amazon.awssdk.services.ssooidc.SsoOidcClient
3941
import software.aws.toolkits.core.TokenConnectionSettings
4042
import software.aws.toolkits.core.utils.test.aString
4143
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
42-
import software.aws.toolkits.jetbrains.core.coroutines.projectCoroutineScope
4344
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
4445
import software.aws.toolkits.jetbrains.core.credentials.ManagedSsoProfile
4546
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
@@ -84,10 +85,13 @@ class CodeWhispererCodeModernizerGumbyClientTest : CodeWhispererCodeModernizerTe
8485
}
8586

8687
streamingBearerClient = mockClientManagerRule.create<CodeWhispererStreamingAsyncClient>().stub {
87-
on { exportResultArchive(any<ExportResultArchiveRequest>(), any<ExportResultArchiveResponseHandler>()) } doReturn CompletableFuture()
88+
on {
89+
exportResultArchive(any<ExportResultArchiveRequest>(), any<ExportResultArchiveResponseHandler>())
90+
} doReturn CompletableFuture.completedFuture(mock()) // void type can't be instantiated
8891
}
8992

9093
amazonQStreamingClient = mock<AmazonQStreamingClient>()
94+
projectRule.project.replaceService(AmazonQStreamingClient::class.java, amazonQStreamingClient, disposableRule.disposable)
9195

9296
val mockConnection = mock<AwsBearerTokenConnection>()
9397
whenever(mockConnection.getConnectionSettings()) doReturn mock<TokenConnectionSettings>()
@@ -165,16 +169,15 @@ class CodeWhispererCodeModernizerGumbyClientTest : CodeWhispererCodeModernizerTe
165169
}
166170

167171
@Test
168-
fun `check downloadExportResultArchive`() {
169-
projectCoroutineScope(project).launch {
170-
whenever(amazonQStreamingClient.exportResultArchive(any<String>(), any<ExportIntent>(), any(), any())) doReturn exampleExportResultArchiveResponse
172+
fun `check downloadExportResultArchive`() = runTest {
173+
whenever(amazonQStreamingClient.exportResultArchive(any<String>(), any<ExportIntent>(), any(), any())) doReturn exampleExportResultArchiveResponse
171174

172-
val actual = gumbyClient.downloadExportResultArchive(jobId)
175+
val actual = gumbyClient.downloadExportResultArchive(jobId)
173176

174-
verifyNoInteractions(bearerClient)
175-
verifyNoInteractions(streamingBearerClient)
176-
assertThat(actual).isInstanceOf(ByteArray::class.java)
177-
assertThat(actual).usingRecursiveComparison().isEqualTo(exampleExportResultArchiveResponse)
178-
}
177+
verify(amazonQStreamingClient).exportResultArchive(eq(jobId.id), eq(ExportIntent.TRANSFORMATION), any(), any())
178+
verifyNoInteractions(bearerClient)
179+
verifyNoInteractions(streamingBearerClient)
180+
verifyNoMoreInteractions(amazonQStreamingClient)
181+
assertThat(actual).usingRecursiveComparison().isEqualTo(exampleExportResultArchiveResponse)
179182
}
180183
}

0 commit comments

Comments
 (0)