Closed nkavian closed 2 years ago
would this work:
public class Foo {
private Bar bar;
// getters/setters, equals/hashcode
}
public class Bar {
public Bar(Object x) {
}
}
@Test
public void test() {
BeanVerifier.forClass(Foo.class)
.withSettings(settings ->
settings.registerFactory(Bar.class, () -> new Bar(RandomValueGenerator.getInstance().nextLong())))
.verifyEqualsAndHashCode();
}
Thanks for sharing the example. Looks like I'm using the v2 code inside 3.0.0-M9
and your example is v3 code.
When using v3 verifyEqualsAndHashCode
with v2 beanTester.testBean
, there's an NPE in the library. There's also a behavior difference between v3 verifyEqualsAndHashCode
and HashCodeMethodTester
.
These issues are mostly on my side since I could just upgrade to v3. Closing the ticket.
When using v3 verifyEqualsAndHashCode with v2 beanTester.testBean, there's an NPE in the library. There's also a behavior difference between v3 verifyEqualsAndHashCode and HashCodeMethodTester.
Curious about NPE and behavior differences
Here is pseudo code to try to explain the scenarios.
A) Testing getters and setters
configuration = new ConfigurationBuilder().overrideFactory("onboarding", () -> new Onboarding(63)).build();
new BeanTester().testBean(target, configuration);
B) Testing hash code
new HashCodeMethodTester().testHashCodeMethod(target);
Initially, I was using Lombok @Data
. Meanbean was then implemented. Then some time later, we decided equality of our models are better suited if we just compare a primaryId of each model file. i.e. public int hashCode() { return Objects.hashCode(primaryId()); }
. Note, (B) still works with this design.
Running A+B works fine.
C) Using your suggestion to use verifyEqualsAndHashCode
in order to access the settings:
BeanVerifier.forClass(target)
.withSettings(settings -> settings.registerFactory(Onboarding.class, () -> new Onboarding(63)))
.verifyEqualsAndHashCode();
C.1) Run just this unit test method and I get Trace 1. I refer to this as the behavior change (when compared to (B)). The message is correct I think, If I have a custom hashCode, then maybe I shouldn't test it with meanbean.
C.2) Run A+C (i.e. run the whole unit test class) and I get Trace 2. I refer to this as the NPE. I don't think it's on my side since all I did was switch B to C / A was untouched.
Trace 1
FAILED: testHashCode
java.lang.AssertionError: objects that differ due to supposedly significant property [enableRamp] were considered equal. (
x.enableRamp=[true]
vs
y.enableRamp=[false]
). is property [enableRamp] actually insignificant?
at org.meanbean.util.AssertionUtils.fail(AssertionUtils.java:51)
at org.meanbean.test.SignificantObjectPropertyEqualityConsistentAsserter.assertConsistent(SignificantObjectPropertyEqualityConsistentAsserter.java:99)
at org.meanbean.test.PropertyBasedEqualsMethodPropertySignificanceVerifier.verifyEqualsMethodForProperty(PropertyBasedEqualsMethodPropertySignificanceVerifier.java:377)
at org.meanbean.test.PropertyBasedEqualsMethodPropertySignificanceVerifier.verifyEqualsMethod(PropertyBasedEqualsMethodPropertySignificanceVerifier.java:266)
at org.meanbean.test.EqualsMethodTester.testEqualsMethod(EqualsMethodTester.java:447)
at org.meanbean.test.EqualsMethodTester.testEqualsMethod(EqualsMethodTester.java:298)
at org.meanbean.test.EqualsMethodTester.testEqualsMethod(EqualsMethodTester.java:232)
at org.meanbean.test.BeanVerifierImpl.verifyEqualsAndHashCode(BeanVerifierImpl.java:70)
Trace 2
FAILED: testGettersAndSetters
java.lang.NullPointerException: context key not available
at java.util.Objects.requireNonNull(Objects.java:228)
at org.meanbean.util.ServiceFactory$ServiceContextMap.getContextMap(ServiceFactory.java:134)
at org.meanbean.util.ServiceFactory.getInstance(ServiceFactory.java:47)
at org.meanbean.util.ServiceDefinition.getServiceFactory(ServiceDefinition.java:60)
at org.meanbean.factories.FactoryCollection.getInstance(FactoryCollection.java:68)
at org.meanbean.factories.BasicNewObjectInstanceFactory.findBeanFactory(BasicNewObjectInstanceFactory.java:43)
at org.meanbean.test.BeanTester.testBean(BeanTester.java:342)
at org.meanbean.test.BeanTester.testBean(BeanTester.java:297)
@nkavian
I am unable to reproduce NPE with the following code. Would you be able to share more details on how to reproduce? Thanks
package example;
import org.junit.Test;
import org.meanbean.test.BeanTester;
import org.meanbean.test.BeanVerifier;
import org.meanbean.test.Configuration;
import org.meanbean.test.ConfigurationBuilder;
import org.meanbean.test.HashCodeMethodTester;
public class MyTest {
public static class Onboarding {
private int id;
private boolean enableRamp;
public Onboarding() {
}
public Onboarding(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isEnableRamp() {
return enableRamp;
}
public void setEnableRamp(boolean enableRamp) {
this.enableRamp = enableRamp;
}
@Override
public int hashCode() {
return id;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Onboarding)) {
return false;
}
Onboarding that = (Onboarding) obj;
return that.id == this.id;
}
}
private final Class<?> target = Onboarding.class;
@Test
public void testA_gettersAndSetters() {
Configuration configuration = new ConfigurationBuilder()
.overrideFactory("onboarding", () -> new Onboarding(63))
.build();
new BeanTester().testBean(target, configuration);
}
@Test
public void testB_hashCode() {
new HashCodeMethodTester().testHashCodeMethod(target);
}
@Test
public void testC_hashCode() {
BeanVerifier.forClass(target)
.withSettings(settings -> settings.registerFactory(Onboarding.class, () -> new Onboarding(63)))
.verifyEqualsAndHashCode();
}
}
When using
BeanTester
, I can provide a configuration that overrides a factory for a field and then pass that configuration in.beanTester.testBean(target, getConfiguration());
When using
HashCodeMethodTester
I don't have that option, and I get the output:Using dynamically created factory for [{}] of type [{}] because a custom Factory cannot be found.
Desired outcome: provide a way to pass in
Configuration
intoHashCodeMethodTester
.