[英]Equalsverifier fails when run with quarkus:dev
When running equalsverfier in quarkus dev mode, equalsverfier tests fail.在 quarkus 开发模式下运行 equalsverfier 时,equalsverfier 测试失败。
I tried to test a class with equalsverifier.我尝试使用 equalsverifier 测试 class。 This works in my IDE.
这适用于我的 IDE。 I tried to use it in quarkus dev mode (by running./mvnw quarkus:dev), but then it fails with the following exception:
我尝试在 quarkus 开发模式下使用它(通过运行 ./mvnw quarkus:dev),但随后失败并出现以下异常:
ERROR [io.qua.test] (Test runner thread) Test DingetjeTest#implementsEquals() failed
: java.lang.AssertionError: EqualsVerifier found a problem in class a.Dingetje.
-> Can not set final java.lang.String field a.Dingetje.text to a.Dingetje
For more information, go to: http://www.jqno.nl/equalsverifier/errormessages
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:308)
at a.DingetjeTest.implementsEquals(DingetjeTest.java:11)
Caused by: java.lang.IllegalArgumentException: Can not set final java.lang.String field a.Dingetje.text to a.Dingetje
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38)
at java.base/java.lang.reflect.Field.get(Field.java:418)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$copyTo$1(FieldModifier.java:79)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$change$3(FieldModifier.java:113)
at nl.jqno.equalsverifier.internal.util.Rethrow.lambda$rethrow$0(Rethrow.java:47)
at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:30)
at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:45)
at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:55)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.change(FieldModifier.java:113)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.copyTo(FieldModifier.java:79)
at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.copyInto(InPlaceObjectAccessor.java:43)
at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.copy(InPlaceObjectAccessor.java:24)
at nl.jqno.equalsverifier.internal.checkers.ExamplesChecker.checkSingle(ExamplesChecker.java:84)
at nl.jqno.equalsverifier.internal.checkers.ExamplesChecker.check(ExamplesChecker.java:47)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verifyWithExamples(SingleTypeEqualsVerifierApi.java:413)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.performVerification(SingleTypeEqualsVerifierApi.java:369)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:304)
... 1 more
Here's the class under test:这是正在测试的 class:
package a;
import java.util.Objects;
public class Dingetje {
private final String text;
public Dingetje(String text) {
this.text = text;
}
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Dingetje)) {
return false;
}
Dingetje other = (Dingetje) o;
return text.equals(other.text);
}
@Override
public final int hashCode() {
return Objects.hash(text);
}
}
And the test:和测试:
package a;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test;
class DingetjeTest {
@Test
void implementsEquals() {
EqualsVerifier.forClass(Dingetje.class)
.withNonnullFields("text")
.verify();
}
}
What am I missing here?我在这里想念什么?
EqualsVerifier uses Objenesis to create instances of classes, and it keeps the same reference of the objenesis object around for performance reasons. EqualsVerifier 使用Objenesis创建类的实例,并且出于性能原因,它保持与对象 object 相同的引用。 It caches all the objects it has created before, so that makes things quicker when you want to create the same object over and over again, which EqualsVerifier tends to do.
它缓存了它之前创建的所有对象,因此当您想要一遍又一遍地创建相同的 object 时,这会使事情变得更快,而 EqualsVerifier 往往会这样做。
However, EqualsVerifier keeps a static reference to objenesis, which means that it lives as long as the JVM does.但是,EqualsVerifier 保留了 static 对对象的引用,这意味着它与 JVM 一样长。 It turns out that the Quarkus test runner can re-run the same tests again and again, and it creates a new class loader each time.
事实证明,Quarkus 测试运行程序可以一次又一次地重新运行相同的测试,并且每次都会创建一个新的 class 加载程序。 But part of the equality of
java.lang.Class
is that the classloader that created the class, must also be the same.但是
java.lang.Class
的部分相等性是创建 class 的类加载器也必须相同。 So it couldn't retrieve these objects from its cache anymore and returnd instances with classloaders that are now different from the other objects created in the test, and this caused the exceptions that you saw.因此,它无法再从其缓存中检索这些对象,并返回带有类加载器的实例,这些类加载器现在与测试中创建的其他对象不同,这导致了您看到的异常。
In version 3.8 of EqualsVerifier (created as a result of this StackOverflow post), this issue can be avoided by adding #withResetCaches()
like this:在 EqualsVerifier 的 3.8 版中(由 StackOverflow 帖子创建),可以通过添加
#withResetCaches()
来避免此问题,如下所示:
EqualsVerifier.forClass(Dingetje.class)
.withResetCaches()
.withNonnullFields("text")
.verify();
That fixes the problem.这解决了问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.