Closed praveenfun2 closed 10 months ago
@praveenfun2
Hello, java.sql.Timestamp
type is not supported by default.
You have to use pushArbitraryIntrospector option to support it.
If you are having trouble using an option, feel free to ask!
Hi @seongahjo, since the value that is set, is null, should it really matter what the data type is ? As we are actually not generating a non null value, do we still need a custom Introspector ?
I also tried
.addExceptGenerateClass(Timestamp::class.java)
but it didn't work
@praveenfun2 Oh, sorry. I did not explain it clearly.
No, if you do not care about the value you generate, You do no need to use the custom ArbitraryIntrospector
The addExceptGenerateClass
option needs to be fixed, it now uses on ArbitraryIntrospector
now,
Instead of using addExceptGenerateClass
, it is better to use the fallback ArbitraryIntrospector
to generate null value.
.objectIntrospector(FailoverIntrospector(
listOf(
BuilderArbitraryIntrospector.INSTANCE,
ConstructorPropertiesArbitraryIntrospector.INSTANCE,
BeanArbitraryIntrospector.INSTANCE,
ArbitraryIntrospector { ArbitraryIntrospectorResult(CombinableArbitrary.from(null as Any?)) }
)
))
Consider the below code
// java
@Builder
public class ABC {
private Timestamp created;
private Child displayDetails;
}
interface Child {
String getPaymentMethodVariant();
class Card implements Child {
private String paymentMethodVariant;
@Override
public String getPaymentMethodVariant() {
return paymentMethodVariant;
}
}
}
// java
// kotlin
var fixtureMonkey: FixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(FailoverIntrospector(
listOf(
BuilderArbitraryIntrospector.INSTANCE,
ConstructorPropertiesArbitraryIntrospector.INSTANCE,
BeanArbitraryIntrospector.INSTANCE
)
))
.pushExactTypeArbitraryIntrospector(Timestamp::class.java) {
ArbitraryIntrospectorResult(CombinableArbitrary.from { null })
}
.defaultNullInjectGenerator(
DefaultNullInjectGenerator(
1.0,
false,
false,
false,
Collections.emptySet(),
Collections.emptySet()
))
.build()
val b2 = fixtureMonkey.giveMeBuilder(ABC::class.java)
val obj2 = b2.sample()
// kotlin
I am expecting that the obj2.displayDetails would be null but instead of that it gets assigned a proxy. Attaching screenshot. Can you help me with how I can make sure default value for displaydetails is always null.
@praveenfun2 This is because Fixture Monkey generates an anonymous object for the interface as default.
Please add a plugin to disable it. It will be disabled as default since 1.1.x.
.plugin(InterfacePlugin().useAnonymousArbitraryIntrospector(false))
Or You can address this issue with adding an option like below.
.objectIntrospector(FailoverIntrospector(
listOf(
BuilderArbitraryIntrospector.INSTANCE,
ConstructorPropertiesArbitraryIntrospector.INSTANCE,
BeanArbitraryIntrospector.INSTANCE,
ArbitraryIntrospector { ArbitraryIntrospectorResult(CombinableArbitrary.from(null as Any?)) }
)
))
@seongahjo Thanks, this seems to fix it. I have another question.
Consider the below code
// java
@Builder
public class ABC {
@Builder.Default
private boolean created = false;
}
// java
// kotlin
var fixtureMonkey: FixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(FailoverIntrospector(
listOf(
BuilderArbitraryIntrospector.INSTANCE,
ConstructorPropertiesArbitraryIntrospector.INSTANCE,
BeanArbitraryIntrospector.INSTANCE,
ArbitraryIntrospector { ArbitraryIntrospectorResult(CombinableArbitrary.from(null as Any?)) }
)
))
.defaultNullInjectGenerator(
DefaultNullInjectGenerator(
1.0,
false,
false,
false,
Collections.emptySet(),
Collections.emptySet()
))
.build()
val b2 = fixtureMonkey.giveMeBuilder(ABC::class.java)
val obj2 = b2.sample()
// kotlin
Sometimes the value for created is false & sometimes its true. My expectation is it'll always remain the same as initialized in the variable, unless modified by manipulators
@praveenfun2
Hello.
In this case, BuilderArbitraryIntrospector
will be used.
BuilderArbitraryIntrospector
generate an instance of ABC
type by a builder method.
The methods of the builder class will generate properties. So created
will be populated randomly even if @Builder.Default
is present.
Currently, the property not randomly populated is not supported except for the default constructor argument. It will be supported in version 1.1.0.
If you want to use an initialized value, you have to use the `set' API to fix it. Thank you.
@seongahjo Ok. I am facing another issue now. Consider the below code
// java
@Data
@Builder
@With
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
public class WWW {
private Map<String, ?> templateAttributes;
}
// java
// kotlin
var fixtureMonkey: FixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(FailoverIntrospector(
listOf(
BuilderArbitraryIntrospector.INSTANCE,
ConstructorPropertiesArbitraryIntrospector.INSTANCE,
BeanArbitraryIntrospector.INSTANCE,
ArbitraryIntrospector { ArbitraryIntrospectorResult(CombinableArbitrary.from(null as Any?)) }
)
))
.defaultNullInjectGenerator(
DefaultNullInjectGenerator(
1.0,
false,
false,
false,
Collections.emptySet(),
Collections.emptySet()
))
.build()
val b2 = fixtureMonkey.giveMeBuilder(WWW::class.java)
val obj2 = b2.sample()
// kotlin
obj2 is coming as null sometimes but sometimes it's being initialized as empty object. My expectation is it'll always be empty object
@praveenfun2
I can not reproduce the issue, obj2
is always not null.
Can you check if it is a valid example?
Hmm, that's strange. I have executed the same code. But when I changed "private Map<String, ?> templateAttributes" to "private Map<String, Object> templateAttributes", I am getting obj2 as non-null. But even in this case, templateAttributes had random values in it. But after using nullableContainer to true, templateAttributes started coming as null. @seongahjo In your system, is templateAttributes null or having random values ? I am expecting that templateAttributes would be null even when I use "?" instead of "Object"
Also, since primitives can't be set to null, is there a way to define default values for them irrespective of classes where they are used ?
@praveenfun2
Oh, I see. I did not think wildcard is actually wildcard.
Since it might be different depending on the situation, it is fixed as Object
.
It may be customizable in the next version.
In this case, You can fix it by adding an option like below.
pushExactTypeArbitraryIntrospector<Object>{
ArbitraryIntrospectorResult(CombinableArbitrary.from(null as Any?))
}
Also, since primitives can't be set to null, is there a way to define default values for them irrespective of classes where they are used ?
You can add a new custom plugin for resolving primitives.
The javaTypeArbitraryGeneratorSet
option in the plugin would be the one you want.
.plugin {
it.javaTypeArbitraryGeneratorSet { ... }
}
Thanks!! I think all the issues are resolved now for me. We can close this one out.
Describe your bug
Consider the below code
Your environment
Steps to reproduce
Execute the above code
Expected behaviour
obj2 should be created with created as null
Actual behaviour
Throws error Failed to generate type "ABC"