[英]Can not Mock a final class in Java
我有一個單元測試,看起來像這樣:
DefaultCloudFoundryOperations cfOperationsMock = mock(DefaultCloudFoundryOperations.class);
when(cfOperationsMock.getSpace()).thenReturn("development");
when(cfOperationsMock.getOrganization()).thenReturn("cloud.foundry.cli");
UserAdmin userAdminMock = mock(UserAdmin.class);
when(cfOperationsMock.userAdmin()).thenReturn(userAdminMock);
Mono<SpaceUsers> monoMock = (Mono<SpaceUsers>) mock(Mono.class);
when(userAdminMock.listSpaceUsers(any())).thenReturn(monoMock);
SpaceUsers spaceUsersMock = mock(SpaceUsers.class);
when(monoMock.block()).thenReturn(spaceUsersMock);
when(spaceUsersMock.getDevelopers())
.thenReturn(Arrays.asList("one", "two", "three", "four"));
SpaceDevelopersProvider spaceDeveloperProvider = new SpaceDevelopersProvider(
cfOperationsMock);
String spaceDevelopers = spaceDeveloperProvider.getSpaceDevelopers();
assertThat(spaceDevelopers, is(Arrays.asList("one", "two", "three", "four")));
和一個 gradle 依賴項,如下所示:
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:28.0-jre'
compile 'info.picocli:picocli:4.2.0'
compile 'org.yaml:snakeyaml:1.26'
// Use JUnit test framework
testRuntime("org.junit.jupiter:junit-jupiter-engine:5.5.2")
testRuntime("org.junit.platform:junit-platform-runner:1.5.2")
testImplementation('org.junit.jupiter:junit-jupiter:5.5.2')
testImplementation 'org.hamcrest:hamcrest:2.2'
testImplementation "org.mockito:mockito-core:2.+"
compile 'io.swagger.parser.v3:swagger-parser:2.0.19'
compile 'org.cloudfoundry:cloudfoundry-client-reactor:4.6.0.RELEASE'
compile 'org.cloudfoundry:cloudfoundry-operations:4.6.0.RELEASE'}
當我嘗試執行此測試時,我收到:
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class org.cloudfoundry.operations.DefaultCloudFoundryOperations.
Can not mock final classes with the following settings :
- explicit serialization (e.g. withSettings().serializable())
- extra interfaces (e.g. withSettings().extraInterfaces(...))
有沒有人有想法,我如何測試它,或者我應該如何調整代碼? 我花了很多時間,但找不到真正適合我的解決方案。
謝謝
在您的生產代碼中(與您的測試代碼相反),不要使用DefaultCloudFoundryOperations
,而是使用它實現的接口: CloudFoundryOperations
例如,像這樣聲明:
public class SpaceDevelopersProvider {
private final CloudFoundryOperations cfOps;
public SpaceDevelopersProvider(CloudFoundryOperations cfOps) {
this.cfOps = cfOps;
}
...
}
然后,您可以模擬該界面。
CloudFoundryOperations cfOperationsMock = mock(CloudFoundryOperations.class);
...
SpaceDevelopersProvider spaceDeveloperProvider = new SpaceDevelopersProvider(cfOperationsMock);
在運行時,當您使用 Mockito 模擬 object 時,它將創建一個代理 class 並擴展您想要模擬的 ZA2F2ED4F8EBC2CBBD4ZC21A 與 java 一樣,最終的 class 無法擴展,因此 mockito 無法模擬最終的 ZA2F2ED4F8EBC2CBB14C21A29DZ4。
從 class ( DefaultCloudFoundryOperations
) 的名稱來看,我猜首先 class 實現了一個接口,其次,所有消費者都將采用該接口,而不是具體的 ZA2F2ED4F8EBC2CBB4C21A29DC40AB61D。
如果我是對的,您可以模擬接口而不是具體的 class。
如前所述,這是一個猜測!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.