我一直在尝试使用 Guice 使用 Cucumber 和 DI 添加集成测试。我有以下目录设置
src/main/kotlin/
\_ com.mypackage.tests
\_ api/ApiGatewayHttpClient.kt
\_ cucumber
\_ api
\_ ApiInfraTestsModule.kt
\_ CucumberInjectorSource.kt
\_ InfraTestsModule.kt
\_ steps
\_ EdgeApiSteps.kt
ApiInfraTestsModule.kt
写法如下:
class ApiInfraTestsModule : AbstractModule() {
private val ROLE_ARN_FORMATTER = "arn:aws:iam::%s:role/%s"
@Provides
@Singleton
fun providesCloudFormationExportsExtractor(): BiFunction<String, String, String> {
return BiFunction { region: String, exportName: String ->
// some CloudFormation logic, return export value
}
}
@Provides
@Singleton
@Named(EDGE_API_ENDPOINT)
fun providesEdgeApiEndpoint(
cloudFormationExportsExtractor: BiFunction<String, String, String>
): String {
val region = Environment.region
return cloudFormationExportsExtractor.apply(
region, EDGE_API_ENDPOINT_EXPORT_NAME
)
}
@Provides
@Singleton
@Named(EDGE_API_UNAUTHORIZED_CREDENTIALS_PROVIDER)
fun providesApiUnauthorizedCredentialsProvider(
// this param is supposed to be injected via `InfraTestsModule.kt`
awsCredentialsProvider: BiFunction<String, String, AwsCredentialsProvider>
): AwsCredentialsProvider {
val region = Environment.region
val roleArn = String.format(
ROLE_ARN_FORMATTER,
Environment.plantFloorAccountId,
Environment.unauthorizedEdgeProvisioningRoleName
)
return awsCredentialsProvider.apply(region, roleArn)
}
@Provides
@Singleton
@Named(EDGE_API_UNAUTHORIZED_CLIENT)
fun providesEdgeApiUnAuthorizedClient(
@Named(EDGE_API_UNAUTHORIZED_CREDENTIALS_PROVIDER)
credentialsProvider: AwsCredentialsProvider
): ApiGatewayHttpClient {
return ApiGatewayHttpClient(
Region.of(Environment.region),credentialsProvider
)
}
}
而
EdgeApiSteps.kt
写成:
class EdgeApiSteps @Inject constructor(
private val testContext: TestContext,
@Named(EDGE_API_ENDPOINT)
private val endpoint: String,
@Named(EDGE_API_UNAUTHORIZED_CLIENT)
private val unauthorizedApiClient: ApiGatewayHttpClient
) {
@When("Provisioning API is called with unauthorized client")
fun executeUnauthorizedApiCall() {
val response = unauthorizedApiClient.get(endpoint)
testContext.apiResponseStatus = response.httpResponse().statusCode()
}
}
当我运行这些测试时,命名注释的依赖注入失败并出现以下错误:
Failed scenarios:
file:////features/security/api/EdgeApi.feature:2 # Provisioning API call with unauthorized principal should fail
1 Scenarios (1 failed)
2 Steps (1 failed, 1 skipped)
0m0.663s
com.google.inject.ConfigurationException: Guice configuration errors:
1) [Guice/MissingImplementation]: No implementation for ApiGatewayHttpClient annotated with @Named(value="EdgeApiUnauthorizedClient") was bound.
Requested by:
1 : EdgeApiSteps.<init>(EdgeApiSteps.kt:11)
\_ for 3rd parameter
while locating EdgeApiSteps
Learn more:
https://github.com/google/guice/wiki/MISSING_IMPLEMENTATION
2) [Guice/MissingImplementation]: No implementation for String annotated with @Named(value="EdgeApi") was bound.
Requested by:
1 : EdgeApiSteps.<init>(EdgeApiSteps.kt:11)
\_ for 2nd parameter
while locating EdgeApiSteps
Learn more:
https://github.com/google/guice/wiki/MISSING_IMPLEMENTATION
2 errors
我看过很多 Guice 示例,似乎 Guice for Kotlin 支持 @Named 注入。但是我根本无法完成这项工作。我不确定 Cucumber 是否能够找到 Guice 模块。我什至剥离了模块,只提供一个 @Named 字符串参数,但它也失败了,并出现了同样的“无实现绑定”错误。
我已经尝试对上述类进行构造函数注入、方法注入、字段注入,但除了上述错误外,这些都没有导致任何结果。