Does anyone have experience with creating an Instancio Model subtype using the properties of a Model supertype is possible? I tried many different ways eventually ending up with the example code, but I can't get it to work. Am I trying to do something that is just not possible? This feature sounds so obvious to me that I cannot imagine that it wouldn't be possible. But at the very least it's very hard to do and I couldn't find documentation about it.
I'm using Instancio 5.4.0 but this code is giving me this error:
Found unused selectors referenced in the following methods:
This is the example code that I am using.
import org.instancio.Instancio;
import org.instancio.Model;
import org.instancio.Select;
import org.instancio.settings.Settings;
import org.junit.jupiter.api.Test;
public class ModelInheritance {
@Test
void modelTest() {
Dog dog = Instancio.create(defaultDogModel());
System.out.println(dog.getSound());
}
private Model<Dog> defaultDogModel() {
return Instancio.of(Dog.class)
.withSettings(Settings.create().mapType(Pet.class, Dog.class))
.set(Select.fields().ofType(Pet.class), Instancio.create(defaultPetModel()))
.set(Select.field(Dog::getSound), "Bark")
.toModel();
}
private Model<Pet> defaultPetModel() {
return Instancio.of(Pet.class)
.set(Select.field(Pet::getName), "Punky")
.set(Select.field(Pet::getColor), "White")
.toModel();
}
}
abstract class Pet {
String name;
String color;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
class Dog extends Pet {
String sound;
public String getSound() {
return sound;
}
public void setSound(String sound) {
this.sound = sound;
}
}
I think the problem is that Select.fields().ofType(Pet.class)
expects an actual field of type Pet
, but since there's no such field in the Dog
class, it fails. You can replace it with a class selector instead. Any of these should work:
Select.types().of(Pet.class)
Select.all(Pet.class)
You can also use Select.root()
because the root object Dog
extends Pet
.
Since you're using a Model
, you might be better off using the setModel()
instead of set()
. Here's an example:
private Model<Dog> defaultDogModel() {
return Instancio.of(Dog.class)
.withSettings(Settings.create().mapType(Pet.class, Dog.class))
.setModel(Select.types().of(Pet.class), defaultPetModel()) // use setModel()
.set(Select.field(Pet::getName), "Fido") // e.g. override name from the model
.set(Select.field(Dog::getSound), "Bark")
.toModel();
}
private Model<Pet> defaultPetModel() {
return Instancio.of(Pet.class)
// mark as lenient() if you're going to override these selectors
.set(Select.field(Pet::getName).lenient(), "Punky")
.set(Select.field(Pet::getColor).lenient(), "White")
.toModel();
}