0

I have the following JUnit parameterized test case which uses an aggregator as well as a directly bonded argument. When I run it, I get the following error: ParameterResolutionException: No ParameterResolver registered for parameter [java.lang.String arg1] in method [void PersonTest.testPersonGreeting(Person,java.lang.String)].

I think that JUnit can't know the index/column for the message argument because the PersonAggregator doesn't specify how many columns it uses. Is there a way to make this test work?

import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.aggregator.AggregateWith;
import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
import org.junit.jupiter.params.aggregator.ArgumentsAggregator;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

class PersonTest {
    static class PersonAggregator implements ArgumentsAggregator {
        @Override
        public Person aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) {
            return new Person(accessor.getString(0), accessor.getInteger(1));
        }
    }

    @ParameterizedTest
    @CsvSource({
            "Alice, 30, 'Hello Alice!'",
            "Bob, 40, 'Hello Bob!'"
    })
    void testPersonGreeting(@AggregateWith(PersonAggregator.class) Person person, String message) {
        assertEquals("Hello " + person.name() + "!", message);
    }
}

record Person(String name, int age) {}

1 Answer 1

0

Here is the solution shown below

To fix this issue, you can use a single ArgumentsAccessor to retrieve all the arguments

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

class PersonTest {
    @ParameterizedTest
    @CsvSource({
            "Alice, 30, 'Hello Alice!'",
            "Bob, 40, 'Hello Bob!'"
    })
    void testPersonGreeting(ArgumentsAccessor accessor) {
        Person person = new Person(accessor.getString(0), accessor.getInteger(1));
        String message = accessor.getString(2);
        assertEquals("Hello " + person.name() + "!", message);
    }
}

record Person(String name, int age) {}

If you want to use an aggregator as custom, you should define another aggregator for string. Here is the code snippet for solution shown below

class PersonTest {
    
    // Aggregator for creating the Person object
    static class PersonAggregator implements ArgumentsAggregator {
        @Override
        public Person aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) {
            return new Person(accessor.getString(0), accessor.getInteger(1));
        }
    }

    // Aggregator for extracting the message
    static class MessageAggregator implements ArgumentsAggregator {
        @Override
        public String aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) {
            return accessor.getString(2);
        }
    }

    @ParameterizedTest
    @CsvSource({
            "Alice, 30, 'Hello Alice!'",
            "Bob, 40, 'Hello Bob!'"
    })
    void testPersonGreeting(
            @AggregateWith(PersonAggregator.class) Person person,
            @AggregateWith(MessageAggregator.class) String message) {
        assertEquals("Hello " + person.name() + "!", message);
    }
}

// Person record definition
record Person(String name, int age) {}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer! Sure, this is possible, but I want the aggregator to create the Object. I could return a Pair<Person, String> by the aggregator or create a second aggregator for the message String, but it don't feels like an optimal solution, e. g. if the arguments differ in another test.
@Silas_229 I editted my post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.