Skip to content

@EmptySource not working with ArgumentConverter accepting its supported types #4801

@scordio

Description

@scordio

Currently, EmptyArgumentsProvider directly checks the type of the first declared parameter and does not know of a potential converter declared for that parameter with its supported type(s), so it will throw a PreconditionViolationException if the declared type doesn't match the expectations.

Looking ahead to when #4219 is integrated, a globally-configured converter might even make the situation more complicated.

Steps to reproduce

Given an ArgumentConverter converting objects to their respective hash codes, like:

class ObjectToHashCodeConverter implements ArgumentConverter {

    @Override
    public Object convert(Object source, ParameterContext context) {
        return source.hashCode();
    }

}

the following test passes:

@ParameterizedTest
@FieldSource
void fieldSourceTest(@ConvertWith(ObjectToHashCodeConverter.class) int hashCode) {
    assertEquals(0, hashCode);
}

static List<?> fieldSourceTest = List.of("");

but the following test does not:

@ParameterizedTest
@EmptySource // no indication on which supported type to use
void emptySourceTest(@ConvertWith(ObjectToHashCodeConverter.class) int hashCode) {
    assertEquals(0, hashCode);
}

failing with:

org.junit.platform.commons.PreconditionViolationException: @EmptySource cannot provide an empty argument to method [void io.github.scordio.junit.converters.tests.MyTest.emptySourceTest(int)]: [int] is not a supported type.

	at org.junit.jupiter.params@5.13.4/org.junit.jupiter.params.provider.EmptyArgumentsProvider.provideArguments(EmptyArgumentsProvider.java:92)
	at org.junit.jupiter.params@5.13.4/org.junit.jupiter.params.ParameterizedInvocationContextProvider.arguments(ParameterizedInvocationContextProvider.java:79)
	at org.junit.jupiter.params@5.13.4/org.junit.jupiter.params.ParameterizedInvocationContextProvider.lambda$provideInvocationContexts$2(ParameterizedInvocationContextProvider.java:46)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.junit.jupiter.engine@5.13.4/org.junit.jupiter.engine.descriptor.TemplateExecutor.executeForProvider(TemplateExecutor.java:59)
	...

Similar reproducers can be composed for all other @EmptySource supported types, like Collection, Map, etc.

Context

  • Used versions (Jupiter/Vintage/Platform): 5.13.4
  • Build Tool/IDE: Maven/IntelliJ IDEA

Deliverables

  • @EmptySource provides an optional type attribute to select the desired type explicitly

Metadata

Metadata

Assignees

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions