This rule raises an issue when a method annotated with TestNG’s @DataProvider returns a type that is not runtime-compatible with TestNG’s expected return types.

Why is this an issue?

TestNG relies on the @DataProvider annotation to supply test data for parameterized tests. At runtime, TestNG expects @DataProvider methods to return one of these types:

Because Java reference arrays are covariant, a String[][] is assignable to Object[][] at runtime, and TestNG can process it just like Object[][]. The same applies to String[] being assignable to Object[]. However, primitive arrays such as int[] or int[][] are not reference types and cannot be assigned to Object[] or Object[][], so TestNG cannot use them.

When a @DataProvider method returns an incompatible type (such as List, Stream, or a primitive array), TestNG cannot process the data correctly. This causes test failures at runtime, even though the code may compile successfully.

Using the wrong return type breaks the runtime contract between your test code and the TestNG framework, leading to:

What is the potential impact?

When a @DataProvider method returns an invalid type, the immediate impact is test execution failure. TestNG will throw a runtime exception when attempting to invoke the test method with the provided data.

This has several consequences:

In CI/CD pipelines, this can block deployments and require emergency fixes to restore test coverage.

How to fix it

Use Object[][] when you have a fixed set of test data. Each inner array represents the parameters for one test invocation.

Code examples

Noncompliant code example

@DataProvider
public List<String> provideData() {  // Noncompliant
    return Arrays.asList("value1", "value2", "value3");
}

Compliant solution

@DataProvider
public Object[][] provideData() {
    return new Object[][] {
        {"value1"},
        {"value2"},
        {"value3"}
    };
}

Use Iterator<Object[]> when you need lazy evaluation or want to generate test data on-the-fly. This is useful for large datasets or when data generation is expensive. Iterator<String[]> is also valid since String[] is assignable to Object[].

Noncompliant code example

@DataProvider
public Stream<String> provideData() {  // Noncompliant
    return Stream.of("value1", "value2", "value3");
}

Compliant solution

@DataProvider
public Iterator<Object[]> provideData() {
    return Arrays.asList(
        new Object[]{"value1"},
        new Object[]{"value2"},
        new Object[]{"value3"}
    ).iterator();
}

Covariant reference arrays such as String[] are assignable to Object[] and are accepted by TestNG. However, primitive arrays such as int[] are not reference arrays and are rejected at runtime.

Noncompliant code example

@DataProvider
public int[] provideIds() {  // Noncompliant, primitive arrays are not assignable to Object[]
    return new int[]{1, 2, 3};
}

Compliant solution

@DataProvider
public String[] provideData() {  // Compliant, String[] is assignable to Object[]
    return new String[]{"value1", "value2", "value3"};
}

Resources

Documentation