diff --git a/api/src/main/java/net/jqwik/api/lifecycle/BeforeTry.java b/api/src/main/java/net/jqwik/api/lifecycle/BeforeTry.java
index 95a08d7df..79221571c 100644
--- a/api/src/main/java/net/jqwik/api/lifecycle/BeforeTry.java
+++ b/api/src/main/java/net/jqwik/api/lifecycle/BeforeTry.java
@@ -7,10 +7,11 @@
import static org.apiguardian.api.API.Status.*;
/**
- * Annotate methods of a container class with {@code @BeforeTry}
- * to have them run once before each try - the actual invocation of the property
+ * Annotate methods or member variables of a container class with {@code @BeforeTry}.
+ * Annotated methods will then be run once before each try - the actual invocation of the property
* method with generated parameters - including properties of
* embedded containers.
+ * Annotated members will be freshly initialized before each try.
*
*
{@code @BeforeTry} methods are inherited from superclasses
* and implemented interfaces as long as they are not hidden
@@ -28,7 +29,7 @@
*
* @see AfterTry
*/
-@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
+@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@API(status = MAINTAINED, since = "1.4.0")
public @interface BeforeTry {
diff --git a/engine/src/main/java/net/jqwik/engine/hooks/Hooks.java b/engine/src/main/java/net/jqwik/engine/hooks/Hooks.java
index 1859429e3..621ca6483 100644
--- a/engine/src/main/java/net/jqwik/engine/hooks/Hooks.java
+++ b/engine/src/main/java/net/jqwik/engine/hooks/Hooks.java
@@ -24,6 +24,9 @@ public static class AroundProperty {
public static class AroundTry {
// Should run close to property method
public static final int TRY_LIFECYCLE_METHODS_PROXIMITY = -10;
+
+ // Should run first thing
+ public static final int BEFORE_TRY_MEMBERS_PROXIMITY = -100;
}
}
diff --git a/engine/src/main/java/net/jqwik/engine/hooks/lifecycle/BeforeTryMembersHook.java b/engine/src/main/java/net/jqwik/engine/hooks/lifecycle/BeforeTryMembersHook.java
new file mode 100644
index 000000000..1e715066a
--- /dev/null
+++ b/engine/src/main/java/net/jqwik/engine/hooks/lifecycle/BeforeTryMembersHook.java
@@ -0,0 +1,63 @@
+package net.jqwik.engine.hooks.lifecycle;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.platform.engine.support.hierarchical.*;
+
+import net.jqwik.api.lifecycle.*;
+import net.jqwik.engine.hooks.*;
+import net.jqwik.engine.support.*;
+
+public class BeforeTryMembersHook implements AroundTryHook {
+
+ private void beforeTry(TryLifecycleContext context) {
+ System.out.println("initialize before try members");
+ // List beforeTryMethods = LifecycleMethods.findBeforeTryMethods(context.containerClass());
+ // callTryMethods(beforeTryMethods, context);
+ }
+
+ private void callTryMethods(List methods, TryLifecycleContext context) {
+ Object testInstance = context.testInstance();
+ ThrowableCollector throwableCollector = new ThrowableCollector(ignore -> false);
+ for (Method method : methods) {
+ Object[] parameters = MethodParameterResolver.resolveParameters(method, context);
+ throwableCollector.execute(() -> callMethod(method, testInstance, parameters));
+ }
+ throwableCollector.assertEmpty();
+ }
+
+ private void callMethod(Method method, Object target, Object[] parameters) {
+ JqwikReflectionSupport.invokeMethodPotentiallyOuter(method, target, parameters);
+ }
+
+ private void afterTry(TryLifecycleContext context) {
+ List afterTryMethods = LifecycleMethods.findAfterTryMethods(context.containerClass());
+ callTryMethods(afterTryMethods, context);
+ }
+
+ @Override
+ public PropagationMode propagateTo() {
+ return PropagationMode.ALL_DESCENDANTS;
+ }
+
+ @Override
+ public boolean appliesTo(Optional element) {
+ return element.map(e -> e instanceof Method).orElse(false);
+ }
+
+ @Override
+ public int aroundTryProximity() {
+ return Hooks.AroundTry.BEFORE_TRY_MEMBERS_PROXIMITY;
+ }
+
+ @Override
+ public TryExecutionResult aroundTry(TryLifecycleContext context, TryExecutor aTry, List