Search code examples
javaspring-bootjunitpoint

Cannot handle with Point (Caused by: java.lang.InstantiationError: org.locationtech.jts.geom.CoordinateSequence) in JUnit Test of Spring Boot


I tried to implement a junit test with the usage of Point in Spring Boot. I completed junit test but I have a problem to handle with Point issue in generateValidUserEntities method of AssignmentEntityBuilder.

How can I fix it?

Here is the AssignmentEntity shown below

...
public class AssignmentEntity extends BaseEntity {

    ...
    
    public void setPoint(double latitude, double longitude) {
        Coordinate coordinate = new Coordinate(latitude, longitude);
        GeometryFactory geometryFactory = new GeometryFactory();
        this.point = geometryFactory.createPoint(coordinate);
    }

}

Here is the AssignmentEntityBuilder shown below

public class AssignmentEntityBuilder extends TestDataBuilder<AssignmentEntity> {

    public AssignmentEntityBuilder() {
        super(AssignmentEntity.class);
    }

    public static List<AssignmentEntity> generateValidUserEntities(int size) {
        List<AssignmentEntity> userEntities = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            AssignmentEntity assignmentEntity = new AssignmentEntityBuilder().withValidFields().build();
            userEntities.add(assignmentEntity);
        }
        return userEntities;
    }

    public AssignmentEntityBuilder withValidFields() {
        InstitutionEntity institutionEntity = new InstitutionEntityBuilder().withValidFields().build();

        double x = Math.random();
        double y = Math.random();
        Point point = new GeometryFactory().createPoint(new Coordinate(x, y));

        return this
                .withId(AysRandomUtil.generateUUID())
                .withInstitutionId(institutionEntity.getId())
                .withInstitution(institutionEntity)
                .withPhoneNumber(new AysPhoneNumberBuilder().withValidFields().build())
                .withDescription("Description")
                .withFirstName("First Name")
                .withLastName("Last Name")
                .withStatus(AssignmentStatus.AVAILABLE)
                .withPoint(point);
    }

    public AssignmentEntityBuilder withId(String id) {
        data.setId(id);
        return this;
    }

    public AssignmentEntityBuilder withInstitutionId(String institutionId) {
        data.setInstitutionId(institutionId);
        return this;
    }

    public AssignmentEntityBuilder withPhoneNumber(AysPhoneNumber phoneNumber) {
        data.setCountryCode(phoneNumber.getCountryCode());
        data.setLineNumber(phoneNumber.getLineNumber());
        return this;
    }

    public AssignmentEntityBuilder withInstitution(InstitutionEntity institution) {
        data.setInstitution(institution);
        return this;
    }

    public AssignmentEntityBuilder withDescription(String description) {
        data.setDescription(description);
        return this;
    }

    public AssignmentEntityBuilder withFirstName(String firstName) {
        data.setFirstName(firstName);
        return this;
    }

    public AssignmentEntityBuilder withLastName(String lastName) {
        data.setLastName(lastName);
        return this;
    }

    public AssignmentEntityBuilder withStatus(AssignmentStatus status) {
        data.setStatus(status);
        return this;
    }

    public AssignmentEntityBuilder withPoint(Point point) {
        data.setPoint(point);
        return this;
    }

}

Here is the service class shown below

class AssignmentSaveServiceImplTest extends AbstractUnitTest {

    @InjectMocks
    private AssignmentSaveServiceImpl assignmentSaveService;

    @Mock
    private AssignmentRepository assignmentRepository;

    @Mock
    private AysIdentity identity;

    @Test
    void givenValidAssignmentSaveRequest_whenAssignmentSaved_thenReturnAssignment() {

        // Given
        AssignmentSaveRequest mockAssignmentSaveRequest = new AssignmentSaveRequestBuilder()
                .withValidFields()
                .build();

        List<AssignmentEntity> assignmentsFromDatabase = AssignmentEntityBuilder.generateValidUserEntities(10);  --- ERROR LINE

        AssignmentEntity mockAssignmentEntity = new AssignmentEntityBuilder()
                .withValidFields().build();

        // When
        Mockito.when(assignmentRepository.findAll())
                .thenReturn(assignmentsFromDatabase);

        Mockito.when(assignmentRepository.save(Mockito.any(AssignmentEntity.class)))
                .thenReturn(mockAssignmentEntity);

        Mockito.when(identity.getInstitutionId())
                .thenReturn(AysRandomUtil.generateUUID());

        // Then
        Assignment assignment = assignmentSaveService.saveAssignment(mockAssignmentSaveRequest);

        Assertions.assertEquals(mockAssignmentSaveRequest.getFirstName(), assignment.getFirstName());
        Assertions.assertEquals(mockAssignmentSaveRequest.getLastName(), assignment.getLastName());
        Assertions.assertEquals(mockAssignmentSaveRequest.getPhoneNumber().getLineNumber(), assignment.getPhoneNumber().getLineNumber());
        Assertions.assertEquals(mockAssignmentSaveRequest.getPhoneNumber().getCountryCode(), assignment.getPhoneNumber().getCountryCode());
        Assertions.assertEquals(mockAssignmentSaveRequest.getDescription(), assignment.getDescription());
        Assertions.assertEquals(mockAssignmentSaveRequest.getDescription(), assignment.getDescription());
        Assertions.assertEquals(mockAssignmentSaveRequest.getLongitude(), assignment.getLongitude());
        Assertions.assertEquals(mockAssignmentSaveRequest.getLatitude(), assignment.getLatitude());

        Mockito.verify(assignmentRepository, Mockito.times(1)).findAll();
        Mockito.verify(identity, Mockito.times(1)).getInstitutionId();
    }
}

Here is the error shown below

org.jeasy.random.ObjectCreationException: Unable to create a random instance of type class com.ays.assignment.model.entity.AssignmentEntity

    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:172)
    at org.jeasy.random.EasyRandom.nextObject(EasyRandom.java:100)
    at com.ays.common.model.TestDataBuilder.<init>(TestDataBuilder.java:39)
    at com.ays.common.model.TestDataBuilder.<init>(TestDataBuilder.java:33)
    at com.ays.assignment.model.entity.AssignmentEntityBuilder.<init>(AssignmentEntityBuilder.java:20)
    at com.ays.assignment.model.entity.AssignmentEntityBuilder.generateValidUserEntities(AssignmentEntityBuilder.java:31)
    at com.ays.assignment.service.impl.AssignmentSaveServiceImplTest.givenValidAssignmentSaveRequest_whenAssignmentSaved_thenReturnAssignment(AssignmentSaveServiceImplTest.java:41)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
    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:156)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    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.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.jeasy.random.ObjectCreationException: Unable to create type: org.locationtech.jts.geom.Point for field: point of class: com.ays.assignment.model.entity.AssignmentEntity
    at org.jeasy.random.FieldPopulator.populateField(FieldPopulator.java:98)
    at org.jeasy.random.EasyRandom.populateField(EasyRandom.java:209)
    at org.jeasy.random.EasyRandom.populateFields(EasyRandom.java:198)
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:165)
    ... 74 more
Caused by: org.jeasy.random.ObjectCreationException: Unable to create a random instance of type class org.locationtech.jts.geom.Point
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:172)
    at org.jeasy.random.FieldPopulator.generateRandomValue(FieldPopulator.java:160)
    at org.jeasy.random.FieldPopulator.populateField(FieldPopulator.java:93)
    ... 77 more
Caused by: org.jeasy.random.ObjectCreationException: Unable to create type: org.locationtech.jts.geom.CoordinateSequence for field: coordinates of class: org.locationtech.jts.geom.Point
    at org.jeasy.random.FieldPopulator.populateField(FieldPopulator.java:98)
    at org.jeasy.random.EasyRandom.populateField(EasyRandom.java:209)
    at org.jeasy.random.EasyRandom.populateFields(EasyRandom.java:198)
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:165)
    ... 79 more
Caused by: org.jeasy.random.ObjectCreationException: Unable to create a random instance of type interface org.locationtech.jts.geom.CoordinateSequence
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:172)
    at org.jeasy.random.FieldPopulator.generateRandomValue(FieldPopulator.java:160)
    at org.jeasy.random.FieldPopulator.populateField(FieldPopulator.java:93)
    ... 82 more
Caused by: org.jeasy.random.ObjectCreationException: Unable to create an instance of type: interface org.locationtech.jts.geom.CoordinateSequence
    at org.jeasy.random.ObjenesisObjectFactory.createInstance(ObjenesisObjectFactory.java:67)
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:147)
    ... 84 more
Caused by: java.lang.InstantiationError: org.locationtech.jts.geom.CoordinateSequence
    at jdk.internal.reflect.GeneratedSerializationConstructorAccessor7.newInstance(Unknown Source)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:484)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
    at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
    at org.jeasy.random.ObjenesisObjectFactory.createNewInstance(ObjenesisObjectFactory.java:78)
    at org.jeasy.random.ObjenesisObjectFactory.createInstance(ObjenesisObjectFactory.java:65)
    ... 85 more

Solution

  • Here is the solution show below

    1 - Define a class named PointRandomizer extending from AbstractRandomizer to generate Point randomly.

    class PointRandomizer extends AbstractRandomizer<Point> {
    
        @Override
        public Point getRandomValue() {
            Coordinate[] coordinates = new Coordinate[]{new Coordinate(40.991739, 29.024168)};
            CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates);
            GeometryFactory geometryFactory = new GeometryFactory();
            return geometryFactory.createPoint(coordinateSequence);
        }
    }
    

    2 - Define a static final variable named PointRandomizer

    private static final PointRandomizer POINT_RANDOMIZER = new PointRandomizer();
    

    3 - Add POINT_RANDOMIZER to EasyRandomParameters to produce point values randomly

    parameters.randomize(Point.class, POINT_RANDOMIZER);
    

    Here is the final TestBuilder class shown below

    public abstract class TestDataBuilder<T> {
        protected final EasyRandom generator;
        protected T data;
        protected Class<T> clazz;
        private static final PositiveIntegerRandomizer POSITIVE_INTEGER_RANDOMIZER = new PositiveIntegerRandomizer();
        private static final LongRangeRandomizer LONG_RANGE_RANDOMIZER = new LongRangeRandomizer(1L, Long.MAX_VALUE);
        private static final CharacterRandomizer CHARACTER_RANDOMIZER = new CharacterRandomizer();
    
        private static final PointRandomizer POINT_RANDOMIZER = new PointRandomizer();
    
    
        public TestDataBuilder(Class<T> clazz) {
            this(clazz, false);
        }
        public TestDataBuilder(Class<T> clazz, boolean excludeRelations) {
            this.clazz = clazz;
            this.generator = new EasyRandom(this.getExclusionParameters(excludeRelations));
            this.data = generator.nextObject(clazz);
        }
        public T build() {
            return data;
        }
        private EasyRandomParameters getExclusionParameters(boolean excludeRelations) {
            EasyRandomParameters parameters = new EasyRandomParameters();
            parameters.randomize(Integer.class, POSITIVE_INTEGER_RANDOMIZER);
            parameters.randomize(String.class, CHARACTER_RANDOMIZER);
            parameters.randomize(Long.class, LONG_RANGE_RANDOMIZER);
            parameters.randomize(Point.class, POINT_RANDOMIZER);
    
            if (!excludeRelations) return parameters;
    
            parameters.excludeField(
                    FieldPredicates.isAnnotatedWith(ManyToOne.class, OneToMany.class, OneToOne.class)
                            .or(named("id"))
            );
            return parameters;
        }
    }
    class PositiveIntegerRandomizer extends IntegerRangeRandomizer {
        private static final int MIN = 0;
        private static final int MAX = 100;
        public PositiveIntegerRandomizer() {
            super(MIN, MAX);
        }
        @Override
        protected Integer getDefaultMinValue() {
            return MIN;
        }
    }
    class CharacterRandomizer extends StringRandomizer {
        @Override
        public String getRandomValue() {
            return RandomStringUtils.randomAlphabetic(10);
        }
    }
    
    
    class PointRandomizer extends AbstractRandomizer<Point> {
    
        @Override
        public Point getRandomValue() {
            Coordinate[] coordinates = new Coordinate[]{new Coordinate(40.991739, 29.024168)};
            CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates);
            GeometryFactory geometryFactory = new GeometryFactory();
            return geometryFactory.createPoint(coordinateSequence);
        }
    }