模拟kotlin单元测试中的Bigquery函数



我正在开发一个单元测试,它涉及(com.google.api.services.bigquery.Bigquery)。我用mock @SpyK来模拟对象。但是当单元测试开始时,every{}块报告错误。详情如下

依赖项为:

"com.google.apis:google-api-services-bigquery:v2-rev20220326-1.32.1"

setUp()函数抛出异常

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(MockKExtension::class, SpringExtension::class)
@EnableConfigurationProperties(ConfidentialTags::class)
@PropertySource(value = ["classpath:application.yml"], factory = YamlPropertySourceFactory::class)
class ResourceAccessServiceTest {
private val mockGoogleCredential = MockGoogleCredential.Builder().build()
@SpyK
private var olderBigQuery: Bigquery = Bigquery.Builder(
MockGoogleCredential.newMockHttpTransportWithSampleTokenResponse(),
mockGoogleCredential.jsonFactory,
mockGoogleCredential
).build()
@InjectMockKs
private lateinit var resourceAccessService: ResourceAccessService
@BeforeAll
fun setUp() {
//error reported here
every { olderBigQuery.RowAccessPolicies().list(any(), any(), any()).execute() } returns mockk() {
every { rowAccessPolicies } returns listOf()
}
}

@Test
fun queryRowAccessExistedPrincipals() {
val list = resourceAccessService.queryRowAccessExistedPrincipals(
TableId.of("proj", "ds", "tbl"),
RowFilter("region", listOf("hk"))
)
assert(list.isEmpty())
}
}

错误日志

java.net.MalformedURLException: no protocol: projects/2af774bb308513d5/datasets/-3e5359fe6b1a603f/tables/-28b905709f94ecc7/rowAccessPolicies
java.lang.IllegalArgumentException: java.net.MalformedURLException: no protocol: projects/2af774bb308513d5/datasets/-3e5359fe6b1a603f/tables/-28b905709f94ecc7/rowAccessPolicies
at com.google.api.client.http.GenericUrl.parseURL(GenericUrl.java:679)
at com.google.api.client.http.GenericUrl.<init>(GenericUrl.java:125)
at com.google.api.client.http.GenericUrl.<init>(GenericUrl.java:108)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequestUrl(AbstractGoogleClientRequest.java:373)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequest(AbstractGoogleClientRequest.java:404)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:514)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:455)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:565)
at com.airwallex.data.grpc.das.service.ResourceAccessServiceTest$setUp$1.invoke(ResourceAccessServiceTest.kt:67)
at com.airwallex.data.grpc.das.service.ResourceAccessServiceTest$setUp$1.invoke(ResourceAccessServiceTest.kt:67)
at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:25)
at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:78)
at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:40)
at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalEvery(API.kt:93)
at io.mockk.MockKKt.every(MockK.kt:98)
at com.airwallex.data.grpc.das.service.ResourceAccessServiceTest.setUp(ResourceAccessServiceTest.kt:67)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptLifecycleMethod(TimeoutExtension.java:126)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptBeforeAllMethod(TimeoutExtension.java:68)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllMethods$9(ClassBasedTestDescriptor.java:384)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllMethods(ClassBasedTestDescriptor.java:382)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:196)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:78)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:136)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)

关键错误信息

java.net.MalformedURLException: no protocol: projects/2af774bb308513d5/datasets/-3e5359fe6b1a603f/tables/-28b905709f94ecc7/rowAccessPolicies

在setUp函数的every{}块中抛出异常。似乎内置在SDK中的url是无效的,没有协议头。但我不知道如何解决这些问题

所以你真正想要的是一种将被测代码与BigQuery解耦的方法。更好的方法是将BigQuery隐藏在你自己的抽象(例如接口)之后,让需要查询的代码只依赖于那个抽象——查阅依赖倒置原理/依赖注入(我在这里有一些答案,展示了一些例子)。这样,您就可以用一个伪实现代替测试,例如,对内存中的集合进行查询。

这种方法还有一个问题。在某些情况下,您确实需要对BigQuery进行实际测试。否则,您将如何证明该组件是有效的?我想这里的可能性受限于贵公司所允许的范围。

最新更新