Search code examples
javaunit-testinginstancio

Instancio assign value based on another class field


I'm going to create a lesson model with fields based on course subject:

Lesson:

@Data
public class Lesson {
    private Long id;
    private Course course;
    private String title;
    private String description;
}

Course:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Course {
    private Long code;
    private String subject;
    private String description;
    private Set<User> users;
}

public static final Model<Lesson> LESSON_TEST_MODEL = Instancio.of(Lesson.class)
            .supply(field(Lesson::getId), () -> START_LESSON_ID.getAndSet(START_LESSON_ID.get() + DEFAULT_INCREMENT_STEP))
            .supply(field(Lesson::getCourse), () -> Instancio.of(COURSE_TEST_MODEL).create())
            .assign(given(field(Course::getSubject), field(Lesson::getTitle))
                    .set(When.is("Mathematics"), "Math Lesson")
                    .set(When.is("History"), "History Lesson")
                    .set(When.is("Literature"), "Literature Lesson")
                    .set(When.is("Physics"), "Physics Lesson")
                    .set(When.is("Computer Science"), "Computer Science Lesson"))
            .assign(given(field(Course::getSubject), field(Lesson::getDescription))
                    .set(When.is("Mathematics"), "Lesson on mathematics concepts")
                    .set(When.is("History"), "Lesson on world history")
                    .set(When.is("Literature"), "Lesson on classical literature")
                    .set(When.is("Physics"), "Lesson on fundamental physics")
                    .set(When.is("Computer Science"), "Lesson on computer programming"))
            .toModel();

But providing this line of code causes an exception:

Reason: unresolved assignment expression

The following assignments could not be applied:

 -> from [field(Course, "subject")] to [field(Lesson, "title")]
 -> from [field(Course, "subject")] to [field(Lesson, "description")]

As a result, the following targets could not be assigned a value:

 -> field Lesson.description (depth=1)
 -> field Lesson.title (depth=1)

How the issue could be resolved?


Solution

  • This error occurs because you are using supply() to set the Lesson.course field:

      .supply(field(Lesson::getCourse), () -> Instancio.of(COURSE_TEST_MODEL).create())
    

    Essentially, you are creating a separate instance of Course and then passing it to supply(). Since the Course was created separately, the second call to Instancio.create() doesn't know what values the course contains. As a result, the assignment is not evaluated and the error is thrown.

    This can be fixed by generating the entire Lesson (including Course) within a single Instancio.create() call:

    public static final Model<Lesson> LESSON_TEST_MODEL = Instancio.of(Lesson.class)
        .supply(field(Lesson::getId), () -> START_LESSON_ID.getAndSet(START_LESSON_ID.get() + DEFAULT_INCREMENT_STEP))
        // generate Course as part of the Lesson instead of using supply()
        .generate(field(Course::getSubject), gen -> gen.oneOf("Mathematics", "History", "Literature", "Physics", "Computer Science"))
        .assign(given(field(Course::getSubject), field(Lesson::getTitle))
                .set(When.is("Mathematics"), "Math Lesson")
                .set(When.is("History"), "History Lesson")
                .set(When.is("Literature"), "Literature Lesson")
                .set(When.is("Physics"), "Physics Lesson")
                .set(When.is("Computer Science"), "Computer Science Lesson"))
        .assign(given(field(Course::getSubject), field(Lesson::getDescription))
                .set(When.is("Mathematics"), "Lesson on mathematics concepts")
                .set(When.is("History"), "Lesson on world history")
                .set(When.is("Literature"), "Lesson on classical literature")
                .set(When.is("Physics"), "Lesson on fundamental physics")
                .set(When.is("Computer Science"), "Lesson on computer programming"))
        .toModel();