reusing models #785
Replies: 9 comments 8 replies
-
Could you provide more details on what you're trying to achieve? What would be the difference between |
Beta Was this translation helpful? Give feedback.
-
Simply want to reuse the rules defined for class A by adding additional rules for sub-class B. |
Beta Was this translation helpful? Give feedback.
-
Tried: @ToString
static class A {
public String f1;
static <T extends A> Model<T> model(Class<T> clazz) {
return Instancio.of(clazz)
.set(field("f1"), "kuku")
.toModel();
}
}
@ToString(callSuper = true)
static class B extends A {
public String f2;
static <T extends A> Model<T> model(Class<T> clazz) {
// ISSUE not sure how or even if possible to remove this cast
return (Model<T>) Instancio.of(A.model(B.class))
.set(field("f2"), "kuku")
.toModel();
}
}
@Test
public void shouldGenerateB() {
// ISSUE fails with invalid field 'f1' for class B
Instancio.of(B.model(B.class))
.stream()
.limit(1)
.forEach(b -> log.debug(b.toString()));
} |
Beta Was this translation helpful? Give feedback.
-
Got it, thank you for the clarification and the example. Your example should work. You just need to specify the class explicitly when using the I was writing another example before I saw your second comment: class PojoA {
String foo;
String getFoo() { return foo; }
}
class PojoB extends PojoA {
String bar;
String getBar() { return bar; }
}
static <T extends PojoA> Model<T> model(Class<T> klass) {
return Instancio.of(klass)
.set(field(PojoA::getFoo), "foo")
.toModel();
}
// Example
Model<PojoA> modelA = model(PojoA.class);
Model<PojoB> modelB = Instancio.of(model(PojoB.class))
.set(field(PojoB::getBar), "bar")
.toModel();
PojoA pojoA = Instancio.create(modelA);
PojoB pojoB = Instancio.create(modelB);
// Output:
// PojoA(foo=foo)
// PojoB(foo=foo, bar=bar) |
Beta Was this translation helpful? Give feedback.
-
Any idea how to remove this down cast? static <T extends A> Model<T> model(Class<T> clazz) {
return (Model<T>) Instancio.of(A.model(B.class))
.set(field("f2"), "kuku")
.toModel();
} |
Beta Was this translation helpful? Give feedback.
-
Seems that I have something workable, but still wondering if this is best approach for achieving reuse. How different Instancio will behave, if the model was to be defined on the C class and specify its rules on descendat members? In my real project I have about 30-40 classes, each containing 10+ fields, and just trying to come up with an workable design. Any suggestions? @ToString
@EqualsAndHashCode
public static class A {
public String f1;
static <T extends A> Model<T> model(Class<T> clazz) {
return Instancio.of(clazz)
.generate(field(A.class, "f1"), oneOf("foo", "bar"))
.toModel();
}
}
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public static class B extends A {
public String f2;
static Model<B> model() {
return Instancio.of(A.model(B.class))
.set(field("f2"), "kuku")
.toModel();
}
}
@ToString
@EqualsAndHashCode
static class C {
B b;
String f3;
static Model<C> model() {
return Instancio.of(C.class)
.supply(field("b"), () -> Instancio.of(B.model()).create())
.set(field("f3"), "muku")
.toModel();
}
}
@Test
public void shouldGenerateC() {
Instancio.of(C.model())
.stream()
.distinct()
.limit(2)
.forEach(b -> log.debug(b.toString()));
} logs:
|
Beta Was this translation helpful? Give feedback.
-
I think there are two options. One is to use models, as in your example: static <T extends A> Model<T> model(Class<T> clazz) { ... } If the classes being created are unrelated (e.g. static <T> Model<T> model(Class<T> clazz) { ... } Then you can create Another option is to create custom generators for your domain classes. You can find a sample implementation in this repository (see the Documentation: |
Beta Was this translation helpful? Give feedback.
-
Usually, for testing we need to construct some object tree , like:
It can be an OrderRequest containing a Payment, a Shipment which further contains an Address, and so on. I envisioned two possible approaches:
I thought that the 2nd approach would quickly become unmaintainable, because any time a field is added/deleted or its semantics are changed, then the Moreover, Perhaps I am missing something? Are there any other approaches? In the documentation it looks like the 2nd approach is suggested (https://www.instancio.org/user-guide/#selector-depth). But again, even with the simple object tree used throughout the documentation: class Person {
String name;
Address homeAddress;
Address workAddress;
}
class Address {
String street;
String city;
List<Phone> phoneNumbers;
}
class Phone {
String areaCode;
String number;
} a |
Beta Was this translation helpful? Give feedback.
-
In addition to the two options above, you can also define custom generators (see #774 (comment)). For example, the generator could be used to create valid objects. If the generator is registered via the SPI, then you could do: Phone phone = Instancio.create(Phone.class);
// Sample output: Phone[areaCode=453, number=3479148] to create an invalid Phone phone = Instancio.of(Phone.class)
.set(field(Phone::getNumber), "invalid")
.create();
// Sample output: Phone[areaCode=523, number=invalid] Usually, I prefer option 2 from your comment above, though I agree that it can get complex if there are many nested classes and collections. I think the approach would depend on your testing requirements. E.g. do you need to create many objects in different states? customise deeply-nested properties and collections? etc. If you create a sample Github repo with some domain classes and specific test cases I could take a look to see what can be done. |
Beta Was this translation helpful? Give feedback.
-
Feature description
Consider having a model defined in a super class.
Is it possible to reuse it in subclasses?
Beta Was this translation helpful? Give feedback.
All reactions