Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit 75cfa17

Browse files
slu-itAxel Schüssler
authored andcommitted
Fixed issues with @nested tests and @Managed browsers
- Factory declaration on class level was not available in @nested classes - Class level Browsers were created multiple times - @nested instance Browsers were never created
1 parent a96b235 commit 75cfa17

File tree

4 files changed

+236
-89
lines changed

4 files changed

+236
-89
lines changed

webtester-support-junit5/src/main/java/info/novatec/testit/webtester/junit5/extensions/BaseExtension.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.util.function.Consumer;
66

77
import org.junit.jupiter.api.extension.ExtensionContext;
8-
import org.junit.jupiter.api.extension.ExtensionContext.Store;
98

109
import lombok.AccessLevel;
1110
import lombok.Getter;
@@ -26,7 +25,6 @@
2625
public class BaseExtension {
2726

2827
protected static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create("testit-webtester");
29-
protected static final String EXTENSION_MODEL_KEY = "extension-model";
3028

3129
private final ReflectionUtils reflectionUtils;
3230
private final TestClassModelFactory testClassModelFactory;
@@ -57,14 +55,8 @@ protected <T extends ExtensionContext> void executeHandlingUndeclaredThrowables(
5755
}
5856

5957
protected final TestClassModel getModel(ExtensionContext context) {
60-
Store store = context.getStore(NAMESPACE);
61-
TestClassModel model = store.get(EXTENSION_MODEL_KEY, TestClassModel.class);
62-
if (model == null) {
63-
Class<?> testClass = getTestClassFrom(context);
64-
model = testClassModelFactory.create(testClass);
65-
store.put(EXTENSION_MODEL_KEY, model);
66-
}
67-
return model;
58+
Class<?> testClass = getTestClassFrom(context);
59+
return testClassModelFactory.create(testClass);
6860
}
6961

7062
private Class<?> getTestClassFrom(ExtensionContext context) {

webtester-support-junit5/src/main/java/info/novatec/testit/webtester/junit5/extensions/browsers/ManagedBrowserExtension.java

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.junit.jupiter.api.AfterEach;
1212
import org.junit.jupiter.api.BeforeAll;
1313
import org.junit.jupiter.api.BeforeEach;
14+
import org.junit.jupiter.api.Nested;
1415
import org.junit.jupiter.api.extension.AfterAllCallback;
1516
import org.junit.jupiter.api.extension.AfterEachCallback;
1617
import org.junit.jupiter.api.extension.BeforeAllCallback;
@@ -25,7 +26,6 @@
2526
import info.novatec.testit.webtester.browser.Browser;
2627
import info.novatec.testit.webtester.browser.BrowserFactory;
2728
import info.novatec.testit.webtester.browser.proxy.ProxyConfiguration;
28-
import info.novatec.testit.webtester.junit5.extensions.NoTestClassException;
2929
import info.novatec.testit.webtester.junit5.extensions.BaseExtension;
3030

3131

@@ -84,7 +84,9 @@ public class ManagedBrowserExtension extends BaseExtension
8484

8585
@Override
8686
public void beforeAll(ContainerExtensionContext context) throws Exception {
87-
executeHandlingUndeclaredThrowables(context, this::initializeAndInjectStaticBrowsers);
87+
if (isRootContext(context)) {
88+
executeHandlingUndeclaredThrowables(context, this::initializeAndInjectStaticBrowsers);
89+
}
8890
}
8991

9092
@Override
@@ -99,7 +101,13 @@ public void afterEach(TestExtensionContext context) {
99101

100102
@Override
101103
public void afterAll(ContainerExtensionContext context) {
102-
getManagedStaticBrowsers(context).forEach(this::closeAndLogErrors);
104+
if (isRootContext(context)) {
105+
getManagedStaticBrowsers(context).forEach(this::closeAndLogErrors);
106+
}
107+
}
108+
109+
private boolean isRootContext(ContainerExtensionContext context) {
110+
return !context.getParent().isPresent();
103111
}
104112

105113
private void closeAndLogErrors(Browser browser) {
@@ -112,10 +120,9 @@ private void closeAndLogErrors(Browser browser) {
112120
}
113121

114122
private void initializeAndInjectStaticBrowsers(ContainerExtensionContext context) {
115-
Class<?> testClass = context.getTestClass().orElseThrow(NoTestClassException::new);
116123
List<Browser> managedBrowsers = getManagedStaticBrowsers(context);
117124
getModel(context).getBrowserFields().stream().filter(isStaticField).forEach(field -> {
118-
Browser browser = createBrowserFor(field, testClass);
125+
Browser browser = createBrowserFor(field);
119126
managedBrowsers.add(browser);
120127
setValue(field, null, browser);
121128
});
@@ -125,36 +132,57 @@ private void initializeAndInjectInstanceBrowsers(TestExtensionContext context) {
125132
Object testInstance = context.getTestInstance();
126133
List<Browser> managedBrowsers = getManagedInstanceBrowsers(context);
127134
getModel(context).getBrowserFields().stream().filter(isInstanceField).forEach(field -> {
128-
Browser browser = createBrowserFor(field, testInstance.getClass());
135+
Browser browser = createBrowserFor(field);
129136
managedBrowsers.add(browser);
130137
setValue(field, testInstance, browser);
131138
});
132139
}
133140

134-
private Browser createBrowserFor(Field field, Class<?> testClass) {
135-
136-
Class<? extends ProxyConfiguration> proxyConfigurationClass;
137-
Class<? extends BrowserFactory> factoryClass;
138-
139-
if (field.isAnnotationPresent(CreateUsing.class)) {
140-
CreateUsing annotation = field.getAnnotation(CreateUsing.class);
141-
proxyConfigurationClass = annotation.proxy();
142-
factoryClass = annotation.value();
143-
} else if (testClass.isAnnotationPresent(CreateBrowsersUsing.class)) {
144-
CreateBrowsersUsing annotation = testClass.getAnnotation(CreateBrowsersUsing.class);
145-
proxyConfigurationClass = annotation.proxy();
146-
factoryClass = annotation.value();
147-
} else {
148-
throw new NoBrowserFactoryException();
141+
private Browser createBrowserFor(Field field) {
142+
143+
CreateUsing createUsing = getFieldLevelAnnotation(field);
144+
if (createUsing != null) {
145+
Class<? extends ProxyConfiguration> proxyConfigurationClass = createUsing.proxy();
146+
Class<? extends BrowserFactory> factoryClass = createUsing.value();
147+
return createBrowser(factoryClass, proxyConfigurationClass);
148+
}
149+
150+
CreateBrowsersUsing createBrowsersUsing = getClassLevelAnnotation(field);
151+
if (createBrowsersUsing != null) {
152+
Class<? extends ProxyConfiguration> proxyConfigurationClass = createBrowsersUsing.proxy();
153+
Class<? extends BrowserFactory> factoryClass = createBrowsersUsing.value();
154+
return createBrowser(factoryClass, proxyConfigurationClass);
155+
}
156+
157+
throw new NoBrowserFactoryException();
158+
159+
}
160+
161+
private CreateUsing getFieldLevelAnnotation(Field field) {
162+
return field.getAnnotation(CreateUsing.class);
163+
}
164+
165+
private CreateBrowsersUsing getClassLevelAnnotation(Field field) {
166+
Class<?> testClass = field.getDeclaringClass();
167+
CreateBrowsersUsing isPresent = testClass.getAnnotation(CreateBrowsersUsing.class);
168+
if (isPresent == null && testClass.isAnnotationPresent(Nested.class)) {
169+
Class<?> declaringClass = testClass.getDeclaringClass();
170+
while (declaringClass != null && isPresent == null) {
171+
isPresent = declaringClass.getAnnotation(CreateBrowsersUsing.class);
172+
declaringClass = declaringClass.getDeclaringClass();
173+
}
149174
}
175+
return isPresent;
176+
}
150177

178+
private Browser createBrowser(Class<? extends BrowserFactory> factoryClass,
179+
Class<? extends ProxyConfiguration> proxyConfigurationClass) {
151180
try {
152181
ProxyConfiguration proxyConfiguration = proxyConfigurationClass.newInstance();
153182
return factoryClass.newInstance().withProxyConfiguration(proxyConfiguration).createBrowser();
154183
} catch (InstantiationException | IllegalAccessException e) {
155184
throw new UndeclaredThrowableException(e, "error while creating browser factory");
156185
}
157-
158186
}
159187

160188
@SuppressWarnings("unchecked")

webtester-support-junit5/src/test/java/info/novatec/testit/webtester/junit5/extensions/BaseExtensionTest.java

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
import static org.junit.jupiter.api.Assertions.assertThrows;
55
import static org.junit.jupiter.api.Assertions.expectThrows;
66
import static org.mockito.Mockito.doReturn;
7-
import static org.mockito.Mockito.mock;
87
import static org.mockito.Mockito.verify;
98
import static org.mockito.Mockito.verifyNoMoreInteractions;
10-
import static org.mockito.Mockito.verifyZeroInteractions;
119

1210
import java.lang.reflect.Field;
1311
import java.lang.reflect.UndeclaredThrowableException;
@@ -27,7 +25,6 @@
2725
import utils.MockitoExtension;
2826

2927
import info.novatec.testit.webtester.junit5.internal.ReflectionUtils;
30-
import info.novatec.testit.webtester.junit5.internal.TestClassModel;
3128
import info.novatec.testit.webtester.junit5.internal.TestClassModelFactory;
3229

3330

@@ -136,60 +133,6 @@ void undeclaredThrowablesAreNotHandled() throws Exception {
136133

137134
}
138135

139-
@Test
140-
@DisplayName("getModel(..) model is returned if it was already loaded")
141-
void modelIsReturnedIfItAlreadyExist() {
142-
143-
TestClassModel model = mock(TestClassModel.class);
144-
doReturn(model).when(store).get(BaseExtension.EXTENSION_MODEL_KEY, TestClassModel.class);
145-
146-
TestClassModel actualModel = cut.getModel(context);
147-
assertThat(actualModel).isSameAs(model);
148-
149-
}
150-
151-
@Test
152-
@DisplayName("getModel(..) model is returned if it was already loaded without invoking producer")
153-
void modelIsReturnedIfItAlreadyExistWithoutProducer() {
154-
155-
TestClassModel model = mock(TestClassModel.class);
156-
doReturn(model).when(store).get(BaseExtension.EXTENSION_MODEL_KEY, TestClassModel.class);
157-
158-
cut.getModel(context);
159-
verifyZeroInteractions(testClassModelFactory);
160-
161-
}
162-
163-
@Test
164-
@DisplayName("getModel(..) model is lazily created if it doesn't exist already")
165-
void modelIsLoadedLazilyIfItDoesNotExist() {
166-
167-
// store does not contain model >> lazy load
168-
doReturn(null).when(store).get(BaseExtension.EXTENSION_MODEL_KEY, TestClassModel.class);
169-
170-
TestClassModel model = mock(TestClassModel.class);
171-
doReturn(model).when(testClassModelFactory).create(TestClass.class);
172-
173-
TestClassModel actualModel = cut.getModel(context);
174-
assertThat(actualModel).isSameAs(model);
175-
176-
}
177-
178-
@Test
179-
@DisplayName("getModel(..) lazily created model is stored")
180-
void modelIsStoredWhenLazilyLoaded() {
181-
182-
// store does not contain model >> lazy load
183-
doReturn(null).when(store).get(BaseExtension.EXTENSION_MODEL_KEY, TestClassModel.class);
184-
185-
TestClassModel model = mock(TestClassModel.class);
186-
doReturn(model).when(testClassModelFactory).create(TestClass.class);
187-
188-
cut.getModel(context);
189-
verify(store).put(BaseExtension.EXTENSION_MODEL_KEY, model);
190-
191-
}
192-
193136
@Test
194137
@DisplayName("getModel(..) exception is thrown if context doesn't contain test class")
195138
void exceptionIfNoTestClass() {

0 commit comments

Comments
 (0)