I'm converting from JUnit to TestNG and facing a issue moving away from the #Rule annotation in JUnit.
In my superclass there is a #Rule, when I change this to #BeforeMethod it simply does not go into that method. (using that Println to confirm)
Also, when i do simply change #Rule or #ClassRule to #BeforeMethod, Eclipse complains that it is 'disallowed at this location'.
(Note I've removed some methods in the below to make the code length a little shorter/easier to view).
public abstract class AbstractTests
{
protected static boolean oneTimeSetUpComplete;
private static Logger log;
private static WebSessionFactory sessionFactory;
private static WcConfigManager config;
private WebSession session;
TestLogger testLogger = new TestLogger(getConfig(), getLog());
private StringBuilder errors = new StringBuilder();
protected WteDataProvider data;
#ClassRule
public static ExternalResource mainConfiguration = new ExternalResource() {
protected void before() throws Throwable {
setUpTests();
};
};
public Verifier errorCollector = new Verifier(){
#Override
protected void verify() throws Throwable {
failTestIfThereAreErrors();
};
};
public TestLogger getTestLogger() {
return testLogger;
}
#Rule
public RuleChain executionOrder() {
return RuleChain.outerRule(getTestLogger()).around(errorCollector);
}
#Rule
public TestRule dataReader = new TestRule() {
public Statement apply(final Statement base,
final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
System.out.println("PRINT IF YOU GO IN HERE");
DataProvider dataProvider = description.getAnnotation(DataProvider.class);
if (dataProvider == null) {
dataProvider = description.getTestClass().getAnnotation(DataProvider.class);
}
base.evaluate();
};
};
};
};
protected AbstractArgosTests(
Logger logger,
WcConfigManager configManager,
WebSessionFactory factory)
{
setUpTests(logger, configManager, factory);
}
}
Related
I have the following class (Condensed it to focus on issue instead of showing entire class):
#Component
public class ABCDEF {
private final Helper helper;
private final URI uri;
public ABCDEF(Helper helper, #Value("${endpoint.url}") URI uri) {
this.helper = helper;
this.uri = uri;
}
public void b(){
helper.toString();
}
}
For its test, I am looking to inject the mocks as follows but it is not working.
The helper comes up as null and I end up having to add a default constructor to be able to throw the URI exception.
Please advice a way around this to be able to properly inject the mocks. Thanks.
#RunWith(JUnitMockitoRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
#InjectMocks
private ABCDEF abcdef = new ABCDEF(
helper,
new URI("test")
);
// adding just to be able to throw Exception
public ABCDEFTest() throws URISyntaxException {
}
#Test
public void b() {
abcdef.b();
}
}
Note: Using Mockito version 1.10.19. Will need to stick to this version.
This should work:
#RunWith(MockitoJUnitRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}
Or, instead of using #RunWith, you can initialize mock inside setUp method:
public class ABCDEFTest {
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
helper = Mockito.mock(Helper.class);
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}
I made my own JUnit-Runner by implementing org.junit.runner.Runner, so that I can run my UnitTests with them using the #RunWith-Annotation.
It lookes somewhat like this:
public class MyRunner extends Runner {
private Context myContext;
myContext.init();
private final BlockJUnit4ClassRunner runner;
public MyRunner(final Class<?> clazz) throws InitializationError {
myContext = new Context();
runner = new BlockJUnit4ClassRunner(clazz);
}
#Override
public void run(final RunNotifier notifier) {
runner.run(notifier);
}
#Override
public Description getDescription() {
return runner.getDescription();
}
public void filter(final Filter filter) throws NoTestsRemainException {
runner.filter(filter);
}
}
To clean up resources, I have to shut down MyContext by calling MyContext.close(). Where should I invoke this so that my resources are cleand up after the tests have run?
I'm not sure what you're trying to achive but have you already had a look at JUnit's Rules?
public class MyContextRule extends ExternalResource {
private final Context myContext;
public MyContextRule() {
myContext = new Context();
}
#Override
protected void before() throws Throwable {
myContext.init();
}
#Override
protected void after() {
myContext.close();
}
}
Usage:
public class MyTest {
#ClassRule
public static MyContextRule contextRule = new MyContextRule();
//...
}
JUnit Rules advantage over Runners is that you can have multiple of them, while you only can have one runner.
So, your custom Rule could be used with any runner that may be introduced by a random testframework that you may come across in the future...
Where should I invoke this so that my resources are cleand up after
the tests have run ?
UPDATED MY ANSWER, you can use org.junit.runner.notification.RunListener as shown below:
(1) Create your own RunListener class:
public class MyRunnerListener extends RunListener {
private Context context;
public MyRunnerListener(Context context) {
this.context = context;
}
void testRunFinished(Result result) {
context.close();
}
}
(2) Use the MyRunnerListener inside MyRunner :
public class MyRunner extends Runner {
private Context myContext;
MyRunnerListener runnerListener;
private final BlockJUnit4ClassRunner runner;
public MyRunner(final Class<?> clazz) throws InitializationError {
myContext = new Context();
myContext.init();
runnerListener = new MyRunnerListener(myContext);
runner = new BlockJUnit4ClassRunner(clazz);
}
#Override
public void run(final RunNotifier notifier) {
notifier.addListener(runnerListener);
runner.run(notifier);
}
#Override
public Description getDescription() {
return runner.getDescription();
}
public void filter(final Filter filter) throws NoTestsRemainException {
runner.filter(filter);
}
}
P.S.: If you don't want to use the Runner, then you can follow the answer from Markus (which uses TestRule, NOT TestRunner).
Please find the below codes and the query mentioned at the last.
**Annotation List**
public interface AnnotationList{
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface QCID {
String[] value();
}
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Author {
String value();
}
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Order {
int value();
}
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyTest {
static class None extends Throwable {
private static final long serialVersionUID = 1L;
private None() {
}}
JUnitLink
public class JunitLink extends BlockJUnit4ClassRunner {
// TODO work in test status to see if things should be run.
public static final Logger logger = LoggerFactory.getLogger(JunitLink.class);
public JunitLink(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
public void run(final RunNotifier notifier) {
JunitLink.super.run(notifier);
}
#Override
protected List<FrameworkMethod> computeTestMethods() {
List<FrameworkMethod> classMethods = getTestClass().getAnnotatedMethods(AnnotationList.MyTest.class);
SortedMap<Integer, FrameworkMethod> sortedTestMethodList = new TreeMap<Integer,FrameworkMethod>();
for (FrameworkMethod seleniumTest : classMethods) {
if (seleniumTest.getAnnotation(AnnotationList.Order.class) != null) {
sortedTestMethodList.put(seleniumTest.getAnnotation(AnnotationList.Order.class).value(),seleniumTest);
}
}
return new ArrayList<FrameworkMethod>(sortedTestMethodList.values());
}
#Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
EachTestNotifier eachNotifier = makeNotifier(method, notifier);
if (method.getAnnotation(Ignore.class) != null) {
runIgnored(eachNotifier);
} else {
runNotIgnored(method, eachNotifier);
}
logger.info("Test {} run completed", method.getName());
}
private int runNotIgnored(FrameworkMethod method,EachTestNotifier eachNotifier) {
int failures = 0;
eachNotifier.fireTestStarted();
try {
methodBlock(method).evaluate();
}
catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
logger.error("Test {} failed!", method.getName());
failures++;
}
catch (Throwable e) {
eachNotifier.addFailure(e);
logger.error("Test {} failed!", method.getName());
failures++;
} finally {
eachNotifier.fireTestFinished();
}
return failures;
}
private void runIgnored(EachTestNotifier eachNotifier) {
eachNotifier.fireTestIgnored();
}
private EachTestNotifier makeNotifier(FrameworkMethod method,RunNotifier notifier) {
Description description = describeChild(method);
return new EachTestNotifier(notifier, description);
}}
Start Up Test
#RunWith(JunitLink.class)
public class StartUp extends SeleneseTestBase {
public static readProperties settings = new readProperties();
public static final Logger LOGGER = LoggerFactory.getLogger(INF.class);
public static WebDriver driver;
public static Actions actions;
#Override
#Before
public void setUp()
{
}
#Override
#After
public void tearDown() {
}
#BeforeClass
public static void StartBrowser() {
//Start Driver etc
}
#AfterClass
public static void tearClassDown() {
//Kill driver
}
}
//Test Cases Are Written Like These
#Author("XXXX")
#QCID({ "Smoke_TC01", "Smoke_TC02", "Smoke_TC03",
"TC04"})
public class SmokeTest extends Startup{
private Components component = new Components();
private String TestDataSheetName = "Smoke";
public SmokeTest() throws Exception {
}
#MyTest
#Order(1)
public void openHomepage() throws Exception {
component.openAPP();
}
#MyTest
#Order(2)
public void Login() throws Exception {
component.Login(USID, PWD);
}
#MyTest
#Order(3)
public void isTerminalLocked() throws Exception {
component.isTerminalLocked();
}
All the test method runs in order. Now I want to run only specific test cases which have runmode as "Yes" declared in a excel. I can add extraline before each test cases to read the lines from excel and run the particular test case but I want to read the excel and pass the selected testcases(based on runmode) to Junit runner.
Please help me.
I think your question is borderline "too broad". It's possible it may get closed for this reason.
Have a look at A JUnit Rule to Conditionally Ignore Tests. From that your isSatisfied() will have to parse your Excel. You can use something like Apache POI to do this.
//registry Class
public class Registry
{
private static final Logger logger = LogFactory
.getLogger(Registry.class);
protected Service service = new serviceMLImpl();
private static Registry instance = new Registry();
public static Registry getInstance()
{
return instance;
}
public static void setInstance(Registry instance)
{
Registry.instance = instance;
}
public Helper getHelper()
{
return new Helper();
}
}
//Helper Class
public class Helper
{
protected Service service = ServiceRegistry
.getService();
public Helper()
{
}
public void sendInfo(Info info)
throws Exception
{
service.sendInfo(info);
}
public void sendFacilitySFPListNotification(
List<GcpFacilitySFPInfo> esfpPortList)
{
gfpGcpService.sendFacilitySFPListNotification(esfpPortList);
}
}
//Test Class
public class RegistryTest
{
Registry registry = new Registry();
Helper helper = createMock(Helper.class);
#Before
public void setUp() throws Exception
{
}
#After
public void tearDown() throws Exception
{
registry = null;
}
#Test
public void testGetInstance()
{
replayAll();
registry.getInstance();
verifyAll();
}
#Test
public void testSetInstance()
{
replayAll();
registry.setInstance(registry);
verifyAll();
}
#Test
public void testGetHelper()
{
**replayAll();
new Helper();
registry.getHelper(); // getting InitializationExceptionError here
verifyAll();** //
}
}
Two classes are there, Helper and Registry class. I tried to write the junit for registry class but got InitializationException in the test class.
This is the error i am getting at registry.getHelper():
java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at
java.lang.Class.forName(Class.java:169) at
javassist.runtime.Desc.getClassObject(Desc.java:44) at
javassist.runtime.Desc.getClassType(Desc.java:153) at
javassist.runtime.Desc.getType(Desc.java:123) at
javassist.runtime.Desc.getType(Desc.java:79) at
com.att.bbnms.cim.gfpgcp.service.ServiceRegistry.getService(ServiceRegistry.java:41) at
com.att.bbnms.cim.nc.service.link.Helper.(Helper.java:14) at
com.att.bbnms.cim.nc.service.link.Registry.getHelper(Registry.java:26) at
com.att.bbnms.cim.nc.service.link.egistryTest.testGetHelper(RegistryTest.java:63) at
org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312) at
org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86) at
org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94) at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296) at
Also while writing the test case for Helper , I am not able to get in the class.
Please tell if you have any solution.
I try to write own junit runner and currently I am stuck at returning proper test description.
public class ParameterizedWrapper extends Suite {
private List<Runner> fRunners;
/**
* #throws Throwable
*
*/
public ParameterizedWrapper(final Class<?> clazz) throws Throwable {
super(clazz, Collections.<Runner>emptyList());
fRunners = constructRunners(getParametersMethod());
}
protected List<Runner> constructRunners(final FrameworkMethod method) throws Exception, Throwable {
#SuppressWarnings("unchecked")
Iterable<Object[]> parameters = (Iterable<Object[]>) getParametersMethod().invokeExplosively(null);
ArrayList<Runner> runners = new ArrayList<Runner>();
int index = 0;
for (Object[] parameter : parameters) {
Class<?> testClass = getTestClass().getJavaClass();
WrappedRunner wrappedRunner = testClass.getAnnotation(WrappedRunner.class);
Runner runner = wrappedRunner.value().getConstructor(Class.class).newInstance(getTestClass().getJavaClass());
runners.add(new WrappingRunner(runner, parameter, testClass, index++));
}
return runners;
}
private FrameworkMethod getParametersMethod() throws Exception {
List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(Parameters.class);
for (FrameworkMethod each : methods) {
if (each.isStatic() && each.isPublic()) {
return each;
}
}
throw new Exception("No public static parameters method on class " + getTestClass().getName());
}
#Override
protected List<Runner> getChildren() {
return fRunners;
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE})
public static #interface WrappedRunner {
Class<? extends Runner> value();
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
public static #interface ParameterSetter {
}
}
class WrappingRunner extends Runner {
private Runner wrappedRunner;
private Object[] parameters;
private Class<?> testClass;
private int testPosition;
public WrappingRunner(final Runner runner, final Object[] params, final Class<?> clazz, final int position) {
wrappedRunner = runner;
parameters = params;
testClass = clazz;
testPosition = position;
}
#Override
public Description getDescription() {
Description originalDescription = wrappedRunner.getDescription();
Description newDescription = Description.createSuiteDescription(nameFor(""), new Annotation[0]);
for (Description child : originalDescription.getChildren()) {
newDescription.addChild(decorateChildDescription(child));
}
return newDescription;
}
private String nameFor(String name) {
return String.format("%1$s[%2$s]", name, testPosition);
}
protected Description decorateChildDescription(final Description originalChildDescription) {
Description d = Description.createTestDescription(originalChildDescription.getTestClass(),
nameFor(originalChildDescription.getMethodName()),
originalChildDescription.getAnnotations().toArray(new Annotation[0]));
return d;
}
#Override
public void run(final RunNotifier notifier) {
try {
ParameterStorage.storeParameters(testClass, parameters);
wrappedRunner.run(notifier);
} finally {
ParameterStorage.clearParameters(testClass);
}
}
}
I have some test class to check if runner works. Runner works fine except tests are named weirdly. In eclipse it displays all tests and adds unrooted tests category
and surefire does not use my naming at all:
I compared description objects generated in my runner and in Parameterized runner, there seems to be no difference.
It's a bit ugly, but it's safer to pass the list of child runners to the parent constructor:
public ParameterizedWrapper(final Class<?> clazz) throws Throwable {
super(clazz, constructRunners(getParametersMethod());
}
private static List<Runner> constructRunners(final FrameworkMethod method)
throws Throwable {
...
You shouldn't need to override Suite.getChildren()
I have checked a bit more and found that description generated by my runner is ok. But that does not matter as it is inconsistent with description used during actual test execution. That is why eclipse shows entries as not executed and that is why surefire does not show my names.
Currently I think to use my own notifier to catch test start point and replace configuration at that point.
If someone has a better solution I would like to know about it :).