Skip to content

Commit

Permalink
Revert back the type requirement of GenericContainer instead of Start…
Browse files Browse the repository at this point in the history
…able.

Signed-off-by: James R. Perkins <[email protected]>
  • Loading branch information
jamezp committed Jul 3, 2024
1 parent 318b3f2 commit 9a70050
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.jboss.arquillian.testcontainers.api.DockerRequired;
import org.jboss.arquillian.testcontainers.api.Testcontainer;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.lifecycle.Startable;
import org.testcontainers.containers.GenericContainer;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
Expand All @@ -47,9 +47,9 @@ public void enrich(final Object testCase) {
.collect(Collectors.toList());
final Testcontainer testcontainer = field.getAnnotation(Testcontainer.class);

// If the field is the default Startable, validate the field is a Startable
if (testcontainer.type() == Startable.class) {
if (!(Startable.class.isAssignableFrom(field.getType()))) {
// If the field is the default GenericContainer, validate the field is a GenericContainer
if (testcontainer.type() == GenericContainer.class) {
if (!(GenericContainer.class.isAssignableFrom(field.getType()))) {
throw new IllegalArgumentException(
String.format("Field %s is not assignable to %s", field, testcontainer.type().getName()));
}
Expand All @@ -62,7 +62,8 @@ public void enrich(final Object testCase) {
}
}

value = instances.get().lookupOrCreate((Class<Startable>) field.getType(), field, testcontainer, qualifiers);
value = instances.get().lookupOrCreate((Class<GenericContainer<?>>) field.getType(), field, testcontainer,
qualifiers);
} catch (Exception e) {
throw new RuntimeException("Could not lookup value for field " + field, e);
}
Expand Down Expand Up @@ -95,9 +96,9 @@ public Object[] resolve(final Method method) {
.filter(a -> !(a instanceof Testcontainer))
.collect(Collectors.toList());

// If the field is the default Startable, validate the field is a Startable
if (testcontainer.type() == Startable.class) {
if (!(Startable.class.isAssignableFrom(parameter.getType()))) {
// If the field is the default GenericContainer, validate the field is a GenericContainer
if (testcontainer.type() == GenericContainer.class) {
if (!(GenericContainer.class.isAssignableFrom(parameter.getType()))) {
throw new IllegalArgumentException(
String.format("Parameter %s is not assignable to %s", parameter,
testcontainer.type().getName()));
Expand All @@ -110,7 +111,8 @@ public Object[] resolve(final Method method) {
.getName()));
}
}
values[i] = instances.get().lookupOrCreate((Class<Startable>) parameter.getType(), parameter, testcontainer,
values[i] = instances.get().lookupOrCreate((Class<GenericContainer<?>>) parameter.getType(), parameter,
testcontainer,
qualifiers);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@
import java.lang.reflect.AnnotatedElement;

import org.jboss.arquillian.testcontainers.api.Testcontainer;
import org.testcontainers.lifecycle.Startable;
import org.testcontainers.containers.GenericContainer;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
class TestcontainerDescription {

final Testcontainer testcontainer;
final Startable instance;
final GenericContainer<?> instance;
final AnnotatedElement element;

TestcontainerDescription(final Testcontainer testcontainer, final AnnotatedElement element, final Startable instance) {
TestcontainerDescription(final Testcontainer testcontainer, final AnnotatedElement element,
final GenericContainer<?> instance) {
this.testcontainer = testcontainer;
this.element = element;
this.instance = instance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import java.util.concurrent.CopyOnWriteArrayList;

import org.jboss.arquillian.testcontainers.api.Testcontainer;
import org.testcontainers.lifecycle.Startable;
import org.testcontainers.containers.GenericContainer;

class TestcontainerRegistry implements Iterable<TestcontainerDescription> {
private final List<TestcontainerDescription> containers;
Expand All @@ -32,18 +32,13 @@ class TestcontainerRegistry implements Iterable<TestcontainerDescription> {
*
* @return the generic type
*/
Startable lookupOrCreate(final Class<Startable> type, final AnnotatedElement element, final Testcontainer testcontainer,
GenericContainer<?> lookupOrCreate(final Class<GenericContainer<?>> type, final AnnotatedElement element,
final Testcontainer testcontainer,
final List<Annotation> qualifiers) {
Startable result = lookup(type, qualifiers);
GenericContainer<?> result = lookup(type, qualifiers);
if (result == null) {
try {
Class<? extends Startable> constructType = (testcontainer.type() == Startable.class) ? type
: testcontainer.type();
if (constructType.isInterface()) {
throw new IllegalArgumentException(
String.format("Type %s is an interface and cannot be created.", constructType));
}
final Constructor<? extends Startable> constructor = constructType.getConstructor();
final Constructor<? extends GenericContainer<?>> constructor = getConstructor(type, testcontainer);
result = constructor.newInstance();
this.containers.add(new TestcontainerDescription(testcontainer, element, result));
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
Expand All @@ -62,7 +57,7 @@ Startable lookupOrCreate(final Class<Startable> type, final AnnotatedElement ele
*
* @return the generic type
*/
Startable lookup(final Class<?> type, final List<Annotation> qualifiers) {
GenericContainer<?> lookup(final Class<?> type, final List<Annotation> qualifiers) {
final List<TestcontainerDescription> foundContainers = new ArrayList<>();
if (qualifiers.isEmpty()) {
for (TestcontainerDescription container : this.containers) {
Expand Down Expand Up @@ -96,4 +91,16 @@ Startable lookup(final Class<?> type, final List<Annotation> qualifiers) {
public Iterator<TestcontainerDescription> iterator() {
return containers.iterator();
}

private static Constructor<? extends GenericContainer<?>> getConstructor(final Class<GenericContainer<?>> type,
final Testcontainer testcontainer) throws NoSuchMethodException {
@SuppressWarnings("unchecked")
Class<? extends GenericContainer<?>> constructType = (testcontainer.type() == GenericContainer.class) ? type
: (Class<? extends GenericContainer<?>>) testcontainer.type();
if (constructType.isInterface()) {
throw new IllegalArgumentException(
String.format("Type %s is an interface and cannot be created.", constructType));
}
return constructType.getConstructor();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;

import org.testcontainers.lifecycle.Startable;
import org.testcontainers.containers.GenericContainer;

/**
* Used to annotate a field or parameter which <strong>must</strong> be an instance of a
* {@link Startable}. A {@link DockerRequired} annotation must be present on the
* {@link GenericContainer}. A {@link DockerRequired} annotation must be present on the
* type to use Testcontainer injection.
*/
@Inherited
Expand All @@ -37,11 +37,11 @@
/**
* The type used to create the value for the field or parameter. The type must have a no-arg constructor.
* <p>
* If left as the default value, {@link Startable}, the type to construct is derived from the
* If left as the default value, {@link GenericContainer}, the type to construct is derived from the
* {@linkplain Field#getType() field} or {@linkplain Parameter#getType() parameter}.
* </p>
*
* @return the type to construct
*/
Class<? extends Startable> type() default Startable.class;
Class<? extends GenericContainer> type() default GenericContainer.class;
}

0 comments on commit 9a70050

Please sign in to comment.