I am trying to execute Junit test using Powershell script. But I keep getting initializationError(SLLTest): No runnable methods
The same test cases run fine from eclipse. I am also overriding the classpath to use the same jars eclipse uses during both compilation and execution.
// TestRunner
import java.io.PrintStream;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestRunner {
public static void main(String[] args) {
PrintStream original = System.out;
Result result = JUnitCore.runClasses(TestSuite.class);
System.setOut(original);
for(Failure failure : result.getFailures())
System.out.println(failure);
if(result.wasSuccessful())
System.out.println("Success");
}
}
// one of the test classes
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.Test;
public class StackQTest{
StackQ s = new StackQ();
#Test
public void pushPopTest() {
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
assertEquals(5, s.pop());
assertEquals(4, s.pop());
assertEquals(3, s.pop());
assertEquals(2, s.pop());
assertEquals(1, s.pop());
}
}
// test suite class
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith (Suite.class)
#SuiteClasses ({SLLTest.class, DLLTest.class, RecursionTest.class,
QueueSTest.class, StackQTest.class})
public class TestSuite {
}
I am expecting "Success" as an output put I always get:
initializationError(SLLTest): No runnable methods
initializationError(DLLTest): No runnable methods
initializationError(RecursionTest): No runnable methods
initializationError(QueueSTest): No runnable methods
initializationError(StackQTest): No runnable methods
Related
JUnit5 does not support PowerMockRunner hence the following code will not work whenever you migrate from JUnit4 to JUnit5.
Eg.
Code you trying to inject mock
import javax.naming.InvalidNameException;
public class Main {
public static void main(String[] args) {
Main main = new Main();
main.publish();
}
public void publish() {
try {
Sample s = new Sample();
s.invoke("Hello");
} catch (InvalidNameException e) {
throw new ServiceFailureException(e.getMessage());
}
}
}
Here you are trying to test publish method where you mock the Sample instance to respond with different responses.
In JUnit4 you could have use PowerMockito to achieve that.
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import javax.naming.InvalidNameException;
#RunWith(PowerMockRunner.class)
#PrepareForTest({Main.class})
public class MainTest {
#Test
public void testPublishSuccess() {
Main m = new Main();
Assert.assertEquals("Expected result not found", "success", m.publish());
}
#Test
public void testPublishFailure() throws Exception{
Sample sample = new Sample();
PowerMockito.when(sample.invoke(Mockito.anyString())).thenReturn("failure");
PowerMockito.whenNew(Sample.class).withNoArguments().thenReturn(sample);
Main m = new Main();
Assert.assertEquals("Expected result not found", "failure", m.publish());
}
#Test(expected = ServiceFailureException.class)
public void testPublishException() throws Exception{
Sample sample = new Sample();
PowerMockito.when(sample.invoke(Mockito.anyString())).thenThrow(new InvalidNameException("Invalid name provided"));
PowerMockito.whenNew(Sample.class).withNoArguments().thenReturn(sample);
Main m = new Main();
m.publish();
}
}
With the introduction of JUnit5, the test cases are failing at mock creating new instances because PowerMockRunner does not support JUnit5.
What is the alternate for using PowerMockito with JUnit5.
As PowerMockito does not support JUnit5, we can use Mockito inline. Here is the code which replace the PowerMockito.
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import javax.naming.InvalidNameException;
public class MainTestJunit5 {
#Test
public void testPublishSuccess() {
Main m = new Main();
Assertions.assertEquals("success", m.publish(), "Expected result not found");
}
#Test
public void testPublishFailure() throws Exception{
try (MockedConstruction<Sample> mockedConstruction = Mockito.mockConstruction(Sample.class, (sampleMock, context) -> {
Mockito.when(sampleMock.invoke(Mockito.anyString())).thenReturn("failure");
})) {
Sample sample = new Sample();
PowerMockito.when(sample.invoke(Mockito.anyString())).thenReturn("failure");
PowerMockito.whenNew(Sample.class).withNoArguments().thenReturn(sample);
Main m = new Main();
Assertions.assertEquals("Expected result not found", "failure", m.publish());
}
}
#Test
public void testPublishException() throws Exception{
try (MockedConstruction<Sample> mockedConstruction = Mockito.mockConstruction(Sample.class, (sampleMock, context) -> {
Mockito.when(sampleMock.invoke(Mockito.anyString())).thenThrow(new InvalidNameException("Invalid name found"));
})){
Main m = new Main();
boolean error = false;
try {
m.publish();
} catch (ServiceFailureException e) {
error = true;
}
Assertions.assertTrue(error, "Exception throwing expected");
}
}
}
Couple of things you need to pay attention
Setting up mockito-inline need additional dependency and an additional configuration.
Extra test runners (PowerMockRunner) and preparation for testing is not needed.
MockedConstruction is scoped, so you have to put all the mocking and processing done within that code block.
JUnit5 messages are the final method argument.
Mockito documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#49
I am trying to write a test for my DAOImpl class, just simply inserting a query
But test is not working, giving such error: junit.framework.AssertionFailedError: No tests found in ...
Cant find any information about this problem.
Test class:
import org.dbunit.Assertion;
import org.dbunit.DBTestCase;
import org.dbunit.PropertiesBasedJdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.junit.jupiter.api.Test;
import test.database.dao.DaoFactory;
import test.database.dao.interfaces.CoursesDao;
import test.models.Course;
import java.io.File;
import static org.junit.jupiter.api.Assertions.*;
public class CoursesDaoImplTest extends DBTestCase {
public CoursesDaoImplTest(String name) {
super(name);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "org.postgresql.Driver");
System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "jdbc:postgresql://localhost:5432/school" );
System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "school_admin" );
System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, "admin" );
}
#Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(new File(getClass().getClassLoader()
.getResource("/school-data.xml").getFile()));
}
#Test
public void TestAdd_ShouldAddCourse_WhenInputNewCourse() throws Exception {
Course course = new Course("Archery", "Description");
CoursesDao coursesDao = DaoFactory.getCoursesDao();
coursesDao.add(course);
IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("courses");
IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(new File(getClass().getClassLoader()
.getResource("/coursesDaoImplTest-add-expected.xml").getFile()));
ITable expectedTable = expectedDataSet.getTable("courses");
Assertion.assertEquals(expectedTable, actualTable);
}
}
DBTestCase is a JUnit 4 class and you are using #Test from JUnit 5. Need to decide which version to use and update accordingly.
Additionally, instead of extending a dbUnit test class, use composition.
I have to Test methods in my code and I wan to execute AfterMehtod for only one. Anybody have any idea how do this?
Here is My code:
package Demo;
import java.util.concurrent.TimeUnit;
import library.Utility;
import org.openqa.selenium.By;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import Pages.custom_actions_page;
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;
public class Custom_Actions extends start {
ExtentReports report;
ExtentTest logger;
String driverPath = "D:\\geckodriver-v0.16.1-win64\\geckodriver.exe";
#Test()
public void signin() throws Exception {
// To Locate the Username field
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
driver.findElement(By.id("username")).sendKeys("admin");
// To locate the Password field
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
driver.findElement(By.id("password")).sendKeys("admin123");
// Click on Login button
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
driver.findElement(By.id("submit")).click();
}
#Test(dependsOnMethods = { "signin" })
public void create_custom_action() {
report = new ExtentReports("D:/Reports/Report.html");
logger = report.startTest("Create Custom Action");
new custom_actions_page(driver).submit();
new custom_actions_page(driver).admin();
new custom_actions_page(driver).custom_ac();
new custom_actions_page(driver).createnew();
new custom_actions_page(driver).nameAs("fortesting").descriptionAs(
"description");
new custom_actions_page(driver).category();
new custom_actions_page(driver).assetsubtype();
new custom_actions_page(driver).assettype();
new custom_actions_page(driver).flintnameAs("hello:example.rb");
new custom_actions_page(driver).submit_butto();
new custom_actions_page(driver).Save_Button();
logger.log(LogStatus.PASS, "Custom Action Created Successfully");
}
#AfterMethod()
public void tearDown(ITestResult result) {
// Here will compare if test is failing then only it will enter into if
// condition
if (ITestResult.FAILURE == result.getStatus()) {
try {
Utility.captureScreenshot(driver, "CustomActionFail.png");
} catch (Exception e) {
System.out.println("Exception while taking screenshot "
+ e.getMessage());
}
}
report.endTest(logger);
report.flush();
driver.close();
}}
#AfterMethod is designed to make your life easier when you need to execute a the same block of code after each test without having to duplicate it in each test. So if you need it to execute only after one test, just embed it into that #Test method and remove the #AfterMethod annotated method.
There are a couple of ways of doing it using what is called as Native Injection within TestNG. For more details on what is the possible combinations for native injection in TestNG please refer here.
The simplest way would be to inspect the name of the #Test method that is about to be executed, from within your #AfterMethod annotated method, and if it matches the name of the method for which you need special execution, you proceed further, else you skip executing the #AfterMethod.
But this is a primitive approach, because if you refactor your test method's name to something else, your approach gets broken.
The other approach is to basically work with a marker interface and do the same logic as described above
Here's a sample that shows all this in action.
The marker annotation would look like below
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
#Target(java.lang.annotation.ElementType.METHOD)
public #interface NeedsSpecialSetup {
}
Now your test class would look like below
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
public class SampleTestClass {
#NeedsSpecialSetup
#Test
public void testMethod1() {
System.err.println("Executing testMethod1()");
}
#Test
public void testMethod2() {
System.err.println("Executing testMethod2()");
}
#AfterMethod
public void afterMethod(Method method) {
NeedsSpecialSetup needsSpecialSetup = method.getAnnotation(NeedsSpecialSetup.class);
if (needsSpecialSetup == null) {
//Don't execute this setup because the method doesn't have the
//special setup annotation.
return;
}
System.err.println("Running special setup for " + method.getName() + "()");
}
}
Notice how we have added the annotation #NeedsSpecialSetup only for the method testMethod1() to indicate that we need the #AfterMethod to be executed only for testMethod1().
Here's the output
Executing testMethod1()
Running special setup for testMethod1()
Executing testMethod2()
===============================================
Default Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================
Gradle is unable to run JUnit tests annotated with:
import org.junit.runners.Parameterized;
#RunWith(value = Paremetrized.class)
public class UnitTest {
// ...
}
There is an official issue for this problem from June 2014 yet unsolved.
Are there any workarounds for enabling those tests (in Gradle 2.4)?
An alternative for JUnit's Parameterized is the open source third-party library junit-dataprovider. It is supported by Gradle (tested with 2.4).
The usage is similar:
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
#RunWith(DataProviderRunner.class)
public class DataProviderTest {
#DataProvider
public static Object[][] dataProviderAdd() {
// #formatter:off
return new Object[][] {
{ 0, 0, 0 },
{ 1, 1, 2 },
/* ... */
};
// #formatter:on
}
#Test
#UseDataProvider("dataProviderAdd")
public void testAdd(int a, int b, int expected) {
// Given:
// When:
int result = a + b;
// Then:
assertEquals(expected, result);
}
}
The dependency line for Gradle:
testCompile 'com.tngtech.java:junit-dataprovider:1.9.3'
I'm trying to mock an external library, however the actual object created in APKDecompiler is being used, instead of the mock object.
Test code
import com.googlecode.dex2jar.v3.Dex2jar;
import jd.core.Decompiler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import APKDecompiler;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.*;
import java.io.File;
import java.io.IOException;
#RunWith(PowerMockRunner.class)
#PrepareForTest({Dex2jar.class})
public class TestAPKDecompiler {
//As this only uses external libraries, I will only test that they are called correctly by mocking them.
#Test
public void testAPKDecompiler() {
try {
File testFile = new File("ApkExtractor/src/test/resources/testApp.jar");
String expectedDirectory = testFile.getAbsolutePath().substring(0, testFile.getAbsolutePath().length() - 4);
mockStatic(Dex2jar.class);
Dex2jar mockApkToProcess = createMock(Dex2jar.class);
Decompiler mockDecompiler = createNiceMockAndExpectNew(Decompiler.class);
expect(Dex2jar.from(testFile)).andStubReturn(mockApkToProcess);
mockApkToProcess.to(new File(expectedDirectory + ".jar"));
expectLastCall();
PowerMock.expectNew(Decompiler.class).andReturn(mockDecompiler).anyTimes();
expect(mockDecompiler.decompileToDir(expectedDirectory + ".jar", expectedDirectory)).andReturn(0);
replay(mockApkToProcess);
PowerMock.replay(mockDecompiler);
replayAll();
String actualDirectory = APKDecompiler.decompileAPKToDirectory(testFile);
verify(mockApkToProcess);
verify(mockDecompiler);
verifyAll();
assertEquals(expectedDirectory, actualDirectory);
testFile.delete();
}
catch(Exception e){
e.printStackTrace();
}
}
}
Class code
import com.googlecode.dex2jar.v3.Dex2jar;
import jd.core.Decompiler;
import jd.core.DecompilerException;
import java.io.File;
import java.io.IOException;
public class APKDecompiler {
public static String decompileAPKToDirectory(File filename) throws IOException, DecompilerException {
String filenameWithoutFileExtension = filename.getAbsolutePath().substring(0, filename.getAbsolutePath().length() - 4);
Dex2jar apkToProcess = Dex2jar.from(filename);
File jar = new File(filenameWithoutFileExtension + ".jar");
apkToProcess.to(jar);
Decompiler decompiler = new Decompiler();
decompiler.decompileToDir(filenameWithoutFileExtension + ".jar", filenameWithoutFileExtension);
return filenameWithoutFileExtension;
}
I've tried this and I haven't had any luck. EasyMock: Mocked object is calling actual method
I get a FileNotFoundException when decompiler.decompileToDir is called, which shouldn't happen as I should be mocking the class.
Any help would be greatly appreciated.
The answer was I didn't include the class i was testing in the #PrepareForTest annotation.
#PrepareForTest({APKDecompiler.class, Dex2jar.class, Decompiler.class})