Skip to content

Configuration methods have the same test class instance when IInvokedMethodListener is being used with @Factory #2560

@RiJo

Description

@RiJo

TestNG Version

7.4.0

7.5.0-SNAPHOT (testng-7.5.0-20210517.112015-26.jar)

7.1.1

Expected behavior

For each configuration method (@​BeforeClass, @​BeforeMethod, etc.) corresponding test class instance created with @​Factory is set in parameters of IInvokedMethodListener calls. E.g. org.testng.ITestNGMethod#getInstance and org.testng.ITestResult#getInstance.

Actual behavior

For most configuration methods (@​BeforeClass, @​BeforeMethod, etc.), the test class instance created with @​Factory is not properly set in parameters of IInvokedMethodListener calls. E.g. org.testng.ITestNGMethod#getInstance and org.testng.ITestResult#getInstance. The behavior is not consistent.

This is a continuation of #2428, where a similar issue was solved but for configuration annotations. This issue is about utlizing the org.testng.IInvokedMethodListener instead.

It is probably causing problems with the solution for #2426, where one now get the factory parameters, but for the wrong test class instance in some cases when @​Factory is used.

Is the issue reproductible on runner?

  • Shell
  • Maven
  • Gradle
  • Ant
  • Eclipse
  • IntelliJ
  • NetBeans

Test case sample 1

@Listeners(FactoryTest.class)
public class FactoryTest implements IInvokedMethodListener {

    @Override
    public void beforeInvocation(final IInvokedMethod method, final ITestResult testResult) {
        System.out.println(method.getTestMethod().getConstructorOrMethod().getName() +
                " - " + method.getTestMethod().getInstance() +
                " - " + testResult.getInstance());
    }

    @Factory
    public static Object[] factory() {
        return new Object[] {
                new FactoryTest(),
                new FactoryTest(),
                new FactoryTest()
        };
    }

    @BeforeClass
    public void beforeClass() {
    }

    @BeforeMethod
    public void beforeMethod() {
    }

    @Test
    public void test() {
    }

    @AfterMethod
    public void afterMethod() {
    }

    @AfterClass
    public void afterClass() {
    }
}

Console output

beforeClass - com.example.FactoryTest@13a5fe33 - com.example.FactoryTest@13a5fe33
beforeMethod - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
test - com.example.FactoryTest@13a5fe33 - com.example.FactoryTest@13a5fe33
afterMethod - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
afterClass - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
beforeClass - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
beforeMethod - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
test - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
afterMethod - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
afterClass - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
beforeClass - com.example.FactoryTest@527740a2 - com.example.FactoryTest@527740a2
beforeMethod - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
test - com.example.FactoryTest@527740a2 - com.example.FactoryTest@527740a2
afterMethod - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc
afterClass - com.example.FactoryTest@3108bc - com.example.FactoryTest@3108bc

===============================================
Default Suite
Total tests run: 3, Passes: 3, Failures: 0, Skips: 0
===============================================

As one can see in the console output, "3108bc" is used in most cases, even though other instances should be used. No more configuration annotations have been tested other than the ones in my example above.

Test case sample 2

Using @​Factory with data provider for the construtor is broken as well:

@Listeners(FactoryTest.Listener.class)
public class FactoryTest {

    public static class Listener implements IInvokedMethodListener {

        @Override
        public void beforeInvocation(final IInvokedMethod method, final ITestResult testResult) {
            System.out.println(method.getTestMethod().getConstructorOrMethod().getName() +
                    " - " + method.getTestMethod().getInstance() +
                    " - " + testResult.getInstance());
            System.out.println("");
        }
    }

    @Factory(dataProvider = "constructorArguments")
    public FactoryTest(final int parameter) {

    }

    @DataProvider
    public static Object[][] constructorArguments() {
        return new Object[][]{{0}, {1}, {2}};
    }

    @BeforeClass
    public void beforeClass() {
    }

    @BeforeMethod
    public void beforeMethod() {
    }

    @Test
    public void test() {
    }

    @AfterMethod
    public void afterMethod() {
    }

    @AfterClass
    public void afterClass() {
    }
}

Console output

beforeClass - com.example.FactoryTest@2b2948e2 - com.example.FactoryTest@2b2948e2
beforeMethod - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
test - com.example.FactoryTest@2b2948e2 - com.example.FactoryTest@2b2948e2
afterMethod - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
afterClass - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
beforeClass - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
beforeMethod - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
test - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
afterMethod - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
afterClass - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
beforeClass - com.example.FactoryTest@eec5a4a - com.example.FactoryTest@eec5a4a
beforeMethod - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
test - com.example.FactoryTest@eec5a4a - com.example.FactoryTest@eec5a4a
afterMethod - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0
afterClass - com.example.FactoryTest@6ddf90b0 - com.example.FactoryTest@6ddf90b0

===============================================
Default Suite
Total tests run: 3, Passes: 3, Failures: 0, Skips: 0
===============================================

Debugging

A conditional break point, arguments.getInstance() != tm.getInstance(), can be put here:
https://github.com/cbeust/testng/blob/4170ef68fb8203265cba4f6bfdbfb9c4a0b63f05/src/main/java/org/testng/internal/ConfigInvoker.java#L315

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions