Skip to content

Commit

Permalink
Allow ITestObjectFactory injection via listeners
Browse files Browse the repository at this point in the history
Closes #2676
  • Loading branch information
krmahadevan committed Nov 20, 2021
1 parent 4c28cd6 commit 2c4e019
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 81 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Current
Fixed: GITHUB-2676: NPE is triggered when working with ITestObjectFactory (Krishnan Mahadevan)
Fixed: GITHUB-2672: Log real stacktrace when test times out. (cdalexndr)
Fixed: GITHUB-2669: A failed retry with ITestContext will lose the ITestContext. (Nan Liang)
Fixed: GITHUB-2643: assertEquals(Set,Set) now ignores ordering as it did before. (Elis Edlund)
Expand Down
15 changes: 9 additions & 6 deletions testng-core/src/main/java/org/testng/SuiteRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ private void init(
!configuration.getObjectFactory().getClass().equals(suite.getObjectFactoryClass());
final ITestObjectFactory suiteObjectFactory;
if (create) {
if (objectFactory == null) {
objectFactory = configuration.getObjectFactory();
}
// Dont keep creating the object factory repeatedly since our current object factory
// Was already created based off of a suite level object factory.
suiteObjectFactory = objectFactory.newInstance(suite.getObjectFactoryClass());
Expand All @@ -166,27 +169,27 @@ private void init(
@Override
public <T> T newInstance(Class<T> cls, Object... parameters) {
try {
return configuration.getObjectFactory().newInstance(cls, parameters);
} catch (Exception e) {
return suiteObjectFactory.newInstance(cls, parameters);
} catch (Exception e) {
return configuration.getObjectFactory().newInstance(cls, parameters);
}
}

@Override
public <T> T newInstance(String clsName, Object... parameters) {
try {
return configuration.getObjectFactory().newInstance(clsName, parameters);
} catch (Exception e) {
return suiteObjectFactory.newInstance(clsName, parameters);
} catch (Exception e) {
return configuration.getObjectFactory().newInstance(clsName, parameters);
}
}

@Override
public <T> T newInstance(Constructor<T> constructor, Object... parameters) {
try {
return configuration.getObjectFactory().newInstance(constructor, parameters);
} catch (Exception e) {
return suiteObjectFactory.newInstance(constructor, parameters);
} catch (Exception e) {
return configuration.getObjectFactory().newInstance(constructor, parameters);
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion testng-core/src/main/java/org/testng/TestRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ private void init(
m_host = suite.getHost();
m_testClassesFromXml = test.getXmlClasses();
m_injectorFactory = m_configuration.getInjectorFactory();
m_objectFactory = m_configuration.getObjectFactory();
m_objectFactory = suite.getObjectFactory();
setVerbose(test.getVerbose());

boolean preserveOrder = test.getPreserveOrder();
Expand Down
15 changes: 13 additions & 2 deletions testng-core/src/main/java/org/testng/internal/ClassImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.testng.ITest;
import org.testng.ITestContext;
import org.testng.ITestObjectFactory;
import org.testng.TestNG;
import org.testng.annotations.ITestAnnotation;
import org.testng.collections.Lists;
import org.testng.collections.Objects;
Expand Down Expand Up @@ -94,7 +95,13 @@ private Object getDefaultInstance(boolean create, String errMsgPrefix) {
if (m_instance != null) {
m_defaultInstance = m_instance;
} else {
IObjectDispenser dispenser = Dispenser.newInstance(m_objectFactory);
ITestObjectFactory factory = m_objectFactory;
Class<?> factoryClass = factory.getClass();
if (factoryClass.isAnonymousClass()
&& factoryClass.getEnclosingClass().equals(TestNG.class)) {
factory = m_testContext.getSuite().getObjectFactory();
}
IObjectDispenser dispenser = Dispenser.newInstance(factory);
BasicAttributes basic = new BasicAttributes(this, null);
DetailedAttributes detailed = newDetailedAttributes(create, errMsgPrefix);
CreationAttributes attributes = new CreationAttributes(m_testContext, basic, detailed);
Expand All @@ -118,7 +125,11 @@ public Object[] getInstances(boolean create, String errorMsgPrefix) {
if (create) {
DetailedAttributes ea = newDetailedAttributes(create, errorMsgPrefix);
CreationAttributes attributes = new CreationAttributes(m_testContext, null, ea);
result = new Object[] {Dispenser.newInstance(m_objectFactory).dispense(attributes)};
result =
new Object[] {
Dispenser.newInstance(m_testContext.getSuite().getObjectFactory())
.dispense(attributes)
};
}
}
if (m_instances.size() > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package test.objectfactory;

import static org.assertj.core.api.Assertions.assertThat;

import org.testng.TestNG;
import org.testng.TestNGException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.xml.XmlSuite;
import test.SimpleBaseTest;
import test.objectfactory.github1131.EmptyConstructorSample;
import test.objectfactory.github1131.IntConstructorSample;
import test.objectfactory.github1131.MyObjectFactory;
import test.objectfactory.github1131.StringConstructorSample;
import test.objectfactory.github1827.GitHub1827Sample;
import test.objectfactory.issue2676.LocalSuiteAlteringListener;
import test.objectfactory.issue2676.LoggingObjectFactorySample;
import test.objectfactory.issue2676.TestClassSample;

public class ObjectFactoryTest extends SimpleBaseTest {

@Test(description = "GITHUB-2676")
public void ensureObjectFactoryIsInvokedWhenAddedViaListeners() {
TestNG testng = create(TestClassSample.class);
testng.addListener(new LocalSuiteAlteringListener());
testng.run();
assertThat(LoggingObjectFactorySample.wasInvoked).isTrue();
}

@Test(
expectedExceptions = TestNGException.class,
expectedExceptionsMessageRegExp = ".*Check to make sure it can be instantiated",
description = "GITHUB-1827")
public void ensureExceptionThrownWhenNoSuitableConstructorFound() {

TestNG testng = create(GitHub1827Sample.class);
testng.run();
}

@Test(dataProvider = "dp", description = "GITHUB-1131")
public void factoryWithEmptyConstructorShouldWork(boolean bool) {
testFactory(bool, EmptyConstructorSample.class);
assertThat(MyObjectFactory.allParams).containsExactly(new Object[] {}, new Object[] {});
}

@Test(dataProvider = "dp", description = "GITHUB-1131")
public void factoryWithIntConstructorShouldWork(boolean bool) {
testFactory(bool, IntConstructorSample.class);
assertThat(MyObjectFactory.allParams).containsExactly(new Object[] {1}, new Object[] {2});
}

@Test(dataProvider = "dp", description = "GITHUB-1131")
public void factoryWithStringConstructorShouldWork(boolean bool) {
testFactory(bool, StringConstructorSample.class);
assertThat(MyObjectFactory.allParams)
.containsExactly(new Object[] {"foo"}, new Object[] {"bar"});
}

private void testFactory(boolean onSuite, Class<?> sample) {
MyObjectFactory.allParams.clear();

XmlSuite suite = createXmlSuite("Test IObjectFactory2", "TmpTest", sample);
TestNG tng = create(suite);

if (onSuite) {
suite.setObjectFactoryClass(MyObjectFactory.class);
} else {
tng.setObjectFactory(MyObjectFactory.class);
}

tng.run();
}

@DataProvider
public static Object[][] dp() {
return new Object[][] {new Object[] {true}, new Object[] {false}};
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package test.objectfactory.issue2676;

import java.util.List;
import org.testng.IAlterSuiteListener;
import org.testng.xml.XmlSuite;

public class LocalSuiteAlteringListener implements IAlterSuiteListener {

@Override
public void alter(List<XmlSuite> suites) {
suites.forEach(each -> each.setObjectFactoryClass(LoggingObjectFactorySample.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package test.objectfactory.issue2676;

import java.lang.reflect.Constructor;
import org.testng.ITestObjectFactory;
import org.testng.internal.objects.InstanceCreator;

public class LoggingObjectFactorySample implements ITestObjectFactory {

public static boolean wasInvoked = false;

@Override
public <T> T newInstance(Constructor<T> constructor, Object... parameters) {
wasInvoked = true;
return InstanceCreator.newInstance(constructor, parameters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package test.objectfactory.issue2676;

import org.testng.annotations.Test;

public class TestClassSample {

@Test
public void sampleTestMethod() {}
}
3 changes: 1 addition & 2 deletions testng-core/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
<class name="test.factory.issue1924.IssueTest"/>
<class name="test.factory.github328.GitHub328Test" />
<class name="test.factory.issue1745.Github1745Test"/>
<class name="test.objectfactory.github1827.GitHub1827Test"/>
<class name="test.objectfactory.ObjectFactoryTest"/>
<class name="test.github1490.VerifyDataProviderListener"/>
<class name="test.listeners.issue2456.IssueTest"/>
<class name="test.methodselection.MethodSelectionTest"/>
Expand Down Expand Up @@ -432,7 +432,6 @@
<class name="test.factory.FactoryIntegrationTest" />
<class name="test.factory.EmptyFactoryDataProviderTest" />

<class name="test.factory.github1131.GitHub1131Test" />
<class name="test.factory.nested.GitHub1307Test"/>

</classes>
Expand Down

0 comments on commit 2c4e019

Please sign in to comment.