smartcat-labs / ranger

Ranger is contextual data generator used to make sensible data for integration tests or to play with it in the database
https://www.smartcat.io/products/ranger-contextual-data-and-load-generator
Apache License 2.0
59 stars 11 forks source link

IllegalArgumentException when using nested object generator #174

Closed milannister closed 7 years ago

milannister commented 7 years ago

Given following domain classes:

public class Pomodoro {

    @Id
    private String id;
    private Instant startedAt;

    private List<PomodoTask> outgoingTasks = Lists.newArrayList();

    private String userId;
    private String username;
    private boolean active;
    private boolean successfullyFinished;
    private int duration;

    public String getId() {
    return id;
    }

    public void setId(String id) {
    this.id = id;
    }

    public List<PomodoTask> getOutgoingTasks() {
    return outgoingTasks;
    }

    public void setOutgoingTasks(List<PomodoTask> outgoingTasks) {
    this.outgoingTasks.clear();
    this.outgoingTasks.addAll(outgoingTasks);
    }

    public String getUserId() {
    return userId;
    }

    public void setUserId(String userId) {
    this.userId = userId;
    }

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public boolean isActive() {
    return active;
    }

    public void setActive(boolean active) {
    this.active = active;
    }

    public int getDuration() {
    return duration;
    }

    public void setDuration(int duration) {
    this.duration = duration;
    }

    public boolean isSuccessfullyFinished() {
    return successfullyFinished;
    }

    public void setSuccessfullyFinished(boolean successfullyFinished) {
    this.successfullyFinished = successfullyFinished;
    }

    public Instant getStartedAt() {
    return startedAt;
    }

    public void setStartedAt(Instant startedAt) {
    this.startedAt = startedAt;
    }

and

public class PomodoTask {

    private LocalDateTime createdAt;
    private String subject;
    private String requesterId;
    private String requesterUsername;
    private String requesterProfileImage;
    private boolean done;

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getRequesterId() {
        return requesterId;
    }
    public void setRequesterId(String requesterId) {
        this.requesterId = requesterId;
    }
    public boolean isDone() {
        return done;
    }
    public void setDone(boolean done) {
        this.done = done;
    }
    public String getRequesterUsername() {
        return requesterUsername;
    }
    public void setRequesterUsername(String requesterUsername) {
        this.requesterUsername = requesterUsername;
    }
    public String getRequesterProfileImage() {
        return requesterProfileImage;
    }
    public void setRequesterProfileImage(String requesterProfileImage) {
        this.requesterProfileImage = requesterProfileImage;
    }

}

When tried to be used in unit test like this:

    .prop("requesterUsername", circular("alice", "bob"))
    .prop("subject", circular("task a", "task b", "task c"))
    .build(PomodoTask.class);

    List<Pomodoro> pomodoroList = new ObjectGeneratorBuilder()
                .prop("duration", circular(3, 4, 5))
                .prop("outgoingTasks", taskBuilder)
                .build(Pomodoro.class).generate(3);

I get the following exception:

java.lang.IllegalArgumentException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: N/A; line: -1, column: -1] (through reference chain: com.collabq.domain.Pomodoro["outgoingTasks"])
    at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3605)
    at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3524)
    at io.smartcat.ranger.core.TypeConverterValue.eval(TypeConverterValue.java:37)
    at io.smartcat.ranger.core.Value.get(Value.java:27)
    at io.smartcat.ranger.ObjectGenerator.buildOne(ObjectGenerator.java:55)
    at io.smartcat.ranger.ObjectGenerator.generate(ObjectGenerator.java:39)
    at com.collabq.service.StatsTOTest.fromPomodoroList_shouldBeInitalizedCorrectly(StatsTOTest.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: N/A; line: -1, column: -1] (through reference chain: com.collabq.domain.Pomodoro["outgoingTasks"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
    at com.fasterxml.jackson.databind.DeserializationContext.reportMappingException(DeserializationContext.java:1234)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1122)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1075)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:338)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:269)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:259)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
    at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3600)
    ... 29 more

If it is wrong usage, maybe it would be good to give friendlier message.

vajda commented 7 years ago

Problem is here: .prop("outgoingTasks", taskBuilder) TaskBuilder will generate only one instance of PomodoTask class, while outgoingTasks expects list.

vajda commented 7 years ago

To solve this, you will need to wrap taskBuilder into list method. However, that way you'll have only one task in each instance. .prop("outgoingTasks", list(taskBuilder))

vajda commented 7 years ago

Functionality you need, is probably still not implemented within Ranger. Take a look at #172 and #173

milannister commented 7 years ago

Yup, not built yet. I thought it was implemented. I'm closing the issue.