我一直在尝试使用 assertJ 作为我团队项目中使用的当前断言库 hamcrest 的替代方案。到目前为止,我有以下课程:
动物.java
package com.assertions.demo.assertj;
public class Animal {
private Species species;
//no arg constructor
public Animal(){}
public Animal(Species species) {
this.species = species;
}
public Species getSpecies() {
return this.species;
}
public enum Species{
DOG(4, true, Environment.LAND),
PIGEON(2, false, Environment.AIR),
OCTOPUS(8, false, Environment.SEA),
ALLIGATOR(4, true, Environment.AMPHIBIOUS);
private int numLegs;
private boolean hasTail;
private Environment environment;
private Species(int numLegs, boolean hasTail, Environment environment) {
this.numLegs = numLegs;
this.hasTail = hasTail;
this.environment = environment;
}
public int getNumLegs(){
return this.numLegs;
}
public boolean hasTail() {
return this.hasTail;
}
public Environment getEnvironment() {
return this.environment;
}
}
public enum Environment {
LAND, SEA, AIR, AMPHIBIOUS
}
}
我为它创建了以下自定义断言:
AnimalAssert.java
package com.assertions.demo.assertj;
import org.assertj.core.api.AbstractAssert;
import com.assertions.demo.assertj.Animal.Environment;
public class AnimalAssert extends AbstractAssert<AnimalAssert, Animal> {
public AnimalAssert(Animal actual, Class<AnimalAssert> selfType) {
super(actual, selfType);
}
public static AnimalAssert assertThat(Animal actual) {
return new AnimalAssert(actual, AnimalAssert.class);
}
public AnimalAssert hasTail(boolean hasTail) {
isNotNull();
if(actual.getSpecies().hasTail() != hasTail) {
String expectedHasTail = hasTail ? "have a tail" : "not have a tail";
String actualHasTail = actual.getSpecies().hasTail() ? "does" : "does not";
failWithMessage("Expected animal to " + expectedHasTail + ", but animal " + actualHasTail + " have a tail");
}
return this;
}
public AnimalAssert livesInEnvironment(Environment env) {
isNotNull();
if(actual.getSpecies().getEnvironment() != env) {
failWithMessage("Expected animal environment to be <%s>, but was <%s>", env, actual.getSpecies().getEnvironment());
}
return this;
}
public AnimalAssert hasNumberOfLegs(int numLegs) {
isNotNull();
if(actual.getSpecies().getNumLegs() != numLegs) {
failWithMessage("Expected animal to have <%s> legs, but animal has <%s> legs", numLegs, actual.getSpecies().getNumLegs());
}
return this;
}
}
根据 AssertJ 功能,我为上述内容提供了一个入口点,并且我正在尝试添加软断言功能:
CustomSoftAssertions.java
package com.demo.assertions.assertj;
import org.assertj.core.api.SoftAssertions;
public class CustomSoftAssertions extends SoftAssertions {
public AnimalAssert assertThat(Animal actual) {
return proxy(AnimalAssert.class, Animal.class, actual);
}
}
当我运行以下测试时:
断言JDemo.java
package com.assertions.demo.assertj;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import com.assertions.demo.assertj.Animal.Environment;
import com.assertions.demo.assertj.Animal.Species;
public class AssertJDemo {
Animal[] testAnimalArray = new Animal[] {
new Animal(Species.ALLIGATOR),
new Animal(Species.DOG),
new Animal(Species.OCTOPUS),
new Animal(Species.PIGEON)
};
@Test
public void softAssertWithCustomAssertionsTest() {
Animal dog = testAnimalArray[1];
CustomSoftAssertions softAssert = new CustomSoftAssertions();
softAssert.assertThat(dog).hasTail(false);
softAssert.assertThat(dog).livesInEnvironment(Environment.AIR);
softAssert.assertThat(dog).hasNumberOfLegs(8);
}
}
我得到以下堆栈跟踪:
org.assertj.core.internal.cglib.core.CodeGenerationException: java.lang.NoSuchMethodException-->com.assertions.demo.assertj.AnimalAssert$$EnhancerByCGLIB$$b5c6715f.<init>(com.assertions.demo.assertj.Animal)
at org.assertj.core.internal.cglib.core.ReflectUtils.getConstructor(ReflectUtils.java:313)
at org.assertj.core.internal.cglib.proxy.Enhancer$EnhancerFactoryData.<init>(Enhancer.java:420)
at org.assertj.core.internal.cglib.proxy.Enhancer.wrapCachedClass(Enhancer.java:709)
at org.assertj.core.internal.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:94)
at org.assertj.core.internal.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.assertj.core.internal.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.assertj.core.internal.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at org.assertj.core.internal.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.assertj.core.internal.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.assertj.core.internal.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.assertj.core.internal.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at org.assertj.core.internal.cglib.proxy.Enhancer.create(Enhancer.java:324)
at org.assertj.core.api.SoftProxies.create(SoftProxies.java:42)
at org.assertj.core.api.AbstractSoftAssertions.proxy(AbstractSoftAssertions.java:31)
at com.assertions.demo.assertj.CustomSoftAssertions.assertThat(CustomSoftAssertions.java:18)
at com.assertions.demo.assertj.AssertJDemo.softAssertWithCustomAssertionsTest(AssertJDemo.java:202)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NoSuchMethodException: com.assertions.demo.assertj.AnimalAssert$$EnhancerByCGLIB$$b5c6715f.<init>(com.assertions.demo.assertj.Animal)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at org.assertj.core.internal.cglib.core.ReflectUtils.getConstructor(ReflectUtils.java:309)
... 39 more
我是在 assertJ 库上做错了什么,还是我违反了一些我没有发现的特定于 java 的东西?我正在使用带有 assertJ 3.8.0 的 Java 8
编辑:我已经根据第一个答案(cglib 需要一个)使用无 arg 构造函数更新了 Animal 类,但抛出了相同的异常