Skip to content

Commit

Permalink
test(TypeHandlerLibrary): RuntimeDelegatingTypeHandler test failure (#…
Browse files Browse the repository at this point in the history
…3992)

This instance of Reflections did not find the test's classes under Java 11; provide an alternate SerializationSandbox.
  • Loading branch information
keturn committed Nov 7, 2021
1 parent 12f9bab commit 4c89465
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 98 deletions.
2 changes: 2 additions & 0 deletions .idea/dictionaries/kevint.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/inspectionProfiles/Terasology.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions subsystems/TypeHandlerLibrary/build.gradle.kts
Expand Up @@ -23,12 +23,15 @@ dependencies {
testRuntimeOnly("org.slf4j:slf4j-simple:1.7.32") {
because("log output during tests")
}
testImplementation(platform("org.junit:junit-bom:5.8.1")) {
// junit-bom will set version numbers for the other org.junit dependencies.
}
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.mockito:mockito-inline:3.12.4")

testImplementation("org.junit.jupiter:junit-jupiter-api:5.5.2")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.5.2")
testImplementation("org.mockito:mockito-junit-jupiter:3.11.2")

testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.5.2")
testImplementation("org.mockito:mockito-junit-jupiter:3.12.4")
}

tasks.register<Test>("unitTest") {
Expand Down
Expand Up @@ -4,8 +4,10 @@

import com.google.common.collect.ImmutableMap;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatcher;
import org.reflections.Reflections;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.terasology.persistence.typeHandling.PersistedData;
import org.terasology.persistence.typeHandling.PersistedDataSerializer;
import org.terasology.persistence.typeHandling.TypeHandler;
Expand All @@ -14,7 +16,7 @@
import org.terasology.persistence.typeHandling.inMemory.AbstractPersistedData;
import org.terasology.persistence.typeHandling.inMemory.PersistedMap;
import org.terasology.persistence.typeHandling.inMemory.PersistedString;
import org.terasology.persistence.typeHandling.reflection.ReflectionsSandbox;
import org.terasology.persistence.typeHandling.reflection.SerializationSandbox;
import org.terasology.reflection.TypeInfo;

import java.lang.reflect.Type;
Expand All @@ -30,136 +32,103 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class RuntimeDelegatingTypeHandlerTest {
private final TypeHandlerLibrary typeHandlerLibrary = mock(TypeHandlerLibrary.class);

private final TypeHandlerContext context =
new TypeHandlerContext(typeHandlerLibrary, new ReflectionsSandbox(new Reflections(getClass().getClassLoader())));

private TypeHandler baseTypeHandler;
private TypeHandler subTypeHandler;
private Class<Sub> subType;
private Type baseType;
private RuntimeDelegatingTypeHandler<Base> runtimeDelegatingTypeHandler;

private static class Base {
int x;
@ExtendWith(MockitoExtension.class)
public class RuntimeDelegatingTypeHandlerTest {
private final TypeHandlerLibrary typeHandlerLibrary;

private final TypeHandler<Base> baseTypeHandler;
private final TypeHandler<Sub> subTypeHandler;
private final Class<Sub> subType = Sub.class;
private final Class<Base> baseType = Base.class;
private final RuntimeDelegatingTypeHandler<Base> runtimeDelegatingTypeHandler;


RuntimeDelegatingTypeHandlerTest(@Mock TypeHandler<Base> baseTypeHandler, @Mock SubHandler subTypeHandler,
@Mock SerializationSandbox sandbox, @Mock TypeHandlerLibrary typeHandlerLibrary) {
this.baseTypeHandler = baseTypeHandler;
this.subTypeHandler = subTypeHandler;
configureMockSerializer(baseTypeHandler);
configureMockSerializer(subTypeHandler);

this.typeHandlerLibrary = typeHandlerLibrary;
// We must mock `getTypeHandler(Type)`, not only `getTypeHandler(Class<>)`
when(typeHandlerLibrary.getTypeHandler((Type) baseType))
.thenReturn(Optional.of(baseTypeHandler));
when(typeHandlerLibrary.getTypeHandler((Type) subType))
.thenReturn(Optional.of(subTypeHandler));

when(sandbox.findSubTypeOf(subType.getName(), baseType))
.thenReturn(Optional.of(subType));
when(sandbox.getSubTypeIdentifier(subType, baseType))
.thenReturn(subType.getName());
TypeHandlerContext context = new TypeHandlerContext(typeHandlerLibrary, sandbox);

runtimeDelegatingTypeHandler = new RuntimeDelegatingTypeHandler<>(
baseTypeHandler, TypeInfo.of(Base.class), context);
}

private static class Sub extends Base {
float y;
}

private void setupHandlers() {
subType = Sub.class;
baseType = TypeInfo.of(Base.class).getType();

abstract class SubHandler extends TypeHandler<Sub> { }

baseTypeHandler = mockTypeHandler();
subTypeHandler = mockTypeHandler(SubHandler.class);

when(typeHandlerLibrary.getTypeHandler(eq(baseType)))
.thenReturn(Optional.of(baseTypeHandler));

when(typeHandlerLibrary.getTypeHandler(eq((Type) subType)))
.thenReturn(Optional.of(subTypeHandler));

runtimeDelegatingTypeHandler = new RuntimeDelegatingTypeHandler<Base>(baseTypeHandler, TypeInfo.of(Base.class), context);
}

private static TypeHandler<?> mockTypeHandler(Class<? extends TypeHandler> subHandlerClass) {
TypeHandler<?> mocked = mock(subHandlerClass);

private static void configureMockSerializer(TypeHandler<?> mocked) {
when(mocked.serialize(any(), any())).thenReturn(new AbstractPersistedData() {
@Override
public boolean isNull() {
return true;
}
});

return mocked;
}

private static TypeHandler<?> mockTypeHandler() {
return mockTypeHandler(TypeHandler.class);
}

@Test
void testSerializeBase() {
PersistedDataSerializer serializer = mock(PersistedDataSerializer.class);
when(serializer.serialize(any(String.class)))
.then(invocation -> new PersistedString((String) invocation.getArguments()[0]));

setupHandlers();

Base base = new Base();
runtimeDelegatingTypeHandler.serialize(base, serializer);

verify(typeHandlerLibrary, never()).getTypeHandler(eq((Type) subType));

verify(baseTypeHandler).serialize(any(), any());
verify(subTypeHandler, never()).serialize(any(), any());

verify(serializer, never()).serialize(
argThat((ArgumentMatcher<Map<String, PersistedData>>) argument -> {
return argument.containsKey(RuntimeDelegatingTypeHandler.TYPE_FIELD);
})
argThat((ArgumentMatcher<Map<String, PersistedData>>) argument -> argument.containsKey(RuntimeDelegatingTypeHandler.TYPE_FIELD))
);
}

@Test
void testSerializeSub() {
PersistedDataSerializer serializer = mock(PersistedDataSerializer.class);
when(serializer.serialize(any(String.class)))
.then(invocation -> new PersistedString((String) invocation.getArguments()[0]));

setupHandlers();
.then(invocation -> new PersistedString((String) invocation.getArguments()[0]));

Base sub = new Sub();
runtimeDelegatingTypeHandler.serialize(sub, serializer);

verify(typeHandlerLibrary, never()).getTypeHandler(eq(baseType));
verify(typeHandlerLibrary).getTypeHandler(eq((Type) subType));

verify(baseTypeHandler, never()).serialize(any(), any());
verify(subTypeHandler).serialize(any(), any());

verify(serializer).serialize(
argThat((ArgumentMatcher<Map<String, PersistedData>>) argument -> {
return argument.get(RuntimeDelegatingTypeHandler.TYPE_FIELD)
.getAsString()
.equals(subType.getName())
&& argument.containsKey(RuntimeDelegatingTypeHandler.VALUE_FIELD);
})
argThat((ArgumentMatcher<Map<String, PersistedData>>) argument -> argument.get(RuntimeDelegatingTypeHandler.TYPE_FIELD)
.getAsString()
.equals(subType.getName())
&& argument.containsKey(RuntimeDelegatingTypeHandler.VALUE_FIELD))
);
}

@Test
void testDeserializeBase() {
setupHandlers();

PersistedData persistedBase = new PersistedMap(ImmutableMap.of());

runtimeDelegatingTypeHandler.deserialize(persistedBase);

verify(typeHandlerLibrary, never()).getTypeHandler(eq((Type) subType));

verify(baseTypeHandler).deserialize(any());
verify(subTypeHandler, never()).deserialize(any());
}

@Test
void testDeserializeSub() {
setupHandlers();

PersistedData persistedSub = new PersistedMap(
ImmutableMap.of(
RuntimeDelegatingTypeHandler.TYPE_FIELD,
new PersistedString(((Class<?>) subType).getName()),
RuntimeDelegatingTypeHandler.VALUE_FIELD,
new PersistedMap(ImmutableMap.of())
)
ImmutableMap.of(
RuntimeDelegatingTypeHandler.TYPE_FIELD,
new PersistedString(subType.getName()),
RuntimeDelegatingTypeHandler.VALUE_FIELD,
new PersistedMap(ImmutableMap.of())
)
);

runtimeDelegatingTypeHandler.deserialize(persistedSub);
Expand All @@ -173,27 +142,33 @@ void testDeserializeSub() {

@Test
void testDeserializeNonSub() {
setupHandlers();

PersistedData persistedData = new PersistedMap(
ImmutableMap.of(
RuntimeDelegatingTypeHandler.TYPE_FIELD,
new PersistedString(Integer.class.getName()),
RuntimeDelegatingTypeHandler.VALUE_FIELD,
new PersistedMap(ImmutableMap.of())
)
ImmutableMap.of(
RuntimeDelegatingTypeHandler.TYPE_FIELD,
new PersistedString(Integer.class.getName()),
RuntimeDelegatingTypeHandler.VALUE_FIELD,
new PersistedMap(ImmutableMap.of())
)
);

Optional<Base> deserialized = runtimeDelegatingTypeHandler.deserialize(persistedData);

assertFalse(deserialized.isPresent());

verify(typeHandlerLibrary, never()).getTypeHandler(eq(baseType));
verify(typeHandlerLibrary, never()).getTypeHandler(eq((Type) subType));
verify(typeHandlerLibrary, never()).getTypeHandler(eq((Type) Integer.class));

verify(subTypeHandler, never()).deserialize(any());
// Serializes using base type handler
verify(baseTypeHandler).deserialize(any());
}

private static class Base {
@SuppressWarnings("unused")
int x;
}

private static class Sub extends Base {
@SuppressWarnings("unused")
float y;
}

private abstract static class SubHandler extends TypeHandler<Sub> { }
}

0 comments on commit 4c89465

Please sign in to comment.