Результат, который вы получаете, точно говорит вам, что происходит.Ни один из ваших методов не вызывает конструктор.
Все ваши методы имеют форму
@Test
@MarkerN
public void fX() {
Z.g();
}
, поэтому они содержат вызов метода static
g()
класса Z
,Но нет экземпляров Z
.
Вместо этого ваши классы A
и B
являются подклассами Z
.Поскольку вы не объявляли для них явные конструкторы, компилятор генерирует для них конструкторы по умолчанию, например
public class A extends Z {
public A() {
super(); // here, the constructor of Z gets called
}
// the other methods …
}
, и поэтому рефлексивный поиск скажет вам, что вызов конструктора Z
происходит внутриметод с именем <init>
, который является конструктором A
, соответственноКонструктор B
для B
.
Было бы иначе, если бы методы делали new Z().g()
, но это сделало бы сомнительным проект, основанный на использовании конструктора, выполняемого до вызова метода static
еще хуже.
Эта проблема должна быть решена на стороне фреймворка, который выполняет оба экземпляра: A
и B
и вызывает для них методы от f1()
до f4()
.Например, с JUnit 5 решение будет выглядеть так:
package test;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedElement;
import org.junit.jupiter.api.*;
public class A {
@BeforeEach
public void prepare(TestInfo ti) {
Z.loadConfiguration(ti.getTestMethod().get());
}
@Test
@Marker1
public void f1() {
Z.g();
}
@Test
@Marker2
public void f2() {
Z.g();
}
}
class Z {
public static void loadConfiguration(AnnotatedElement e) {
if(e.isAnnotationPresent(Marker1.class)) {
System.out.println("Marker1");
}
else if(e.isAnnotationPresent(Marker2.class)) {
System.out.println("Marker2");
}
}
public static void g() {
System.out.println("Z.g()");
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface Marker1 {}
@Retention(RetentionPolicy.RUNTIME)
@interface Marker2 {}
Marker1
Z.g()
Marker2
Z.g()