How run junit with parametrized constructor - java

I have to run junit test from command line and one of the guy in the team created junit classes like below:
public Test extends TestCore
{
String some;
public Test(String some)
{
this.some = some;
}
//some test here
}
this work from the eclipse but doesn't from command line.
The result of execution this kind of file gave me error like below:
Test class should have exactly one public zero-argument constructor.
Anyone could help me?
Cheers Jaroslaw.

Eclipse uses a different testrunner. Maybe the parameterized constructors are caused by TestCore being a parameterized test, e.g. like this:
#RunWith(Parameterized.class)
public class TestCore {
String someThatWillBeHidden;
public TestCore(String some) {
this.someThatWillBeHidden = some;
}
#Parameters
public static List<Object[]> data() {
Object[][] data = new Object[][] { {"Hello"}, {" "}, {"world"}};
return Arrays.asList(data);
}
//some test here
}
So which version of junit are you using?

Related

springboot mockito JUnit 5 Command builder pattern service unit test

I'm writing the unit test to code that I wrote for a service class. Here is the short part of my class for the question(s) I have:
public interface Command { public void execute(); }
public class MyServiceClass {
private void doBusinessLogicValidation() {...}
private void doBusinessLogicValidation2() {...}
public void myMethod() {
doBusinessLogicValidation();
doBusinessLogicValidation2();
Command myCommand = callPrivateMethodToCreateMyCommand();
myCommand.execute();
}
private Command callPrivateMethodToCreateMyCommand() {
MyObject commandObject = MyObject.builder().add("something").additional("else").build();
return commandObject;
}
}
The above code is fine and works w/ no problem and uses Java access modifiers correctly: short and concise. For the unit test, I need to override the callPrivateMethodToCreateMyCommand, but it is (correctly) private. PowerMock does not support JUnit 5.
I can change the callPrivateMethodToCreateMyCommand() to public and easily use JUnit's when()...thenReturn() semantics. BUT that breaks encapsulation and the reason why one would use private. And do not want to use protected.
My unit of test is the MyServiceClass and NOT into the execute() method of myCommand. What am I missing?
Any help would be appreciated.
Thanks,Jim

blend parameterized and programmatic unit tests

With JUnit you can use #RunWith(Parameterized.class) to provide a set of parameters to pass to the test constructor and then run tests with each object.
I'm trying to move as much test logic as possible into data, but there are some tests that won't easily be converted into data-driven tests. Is there a way to use JUnit's Parameterized runner to run some tests with parameters, and then also add non-data-driven tests that aren't run repeatedly for each test object construction?
My workaround for this was to create a single class and place the programmatic and data-driven tests in two separate sub-classes. A sub-class must be static for JUnit to run its tests. Here's a skeleton:
#RunWith(Enclosed.class) // needed for working well with Ant
public class MyClassTests {
public static class Programmatic {
#Test
public void myTest(){
// test something here
}
}
#RunWith(Parameterized.class)
public static class DataDriven {
#Parameters
public static Collection<Object[]> getParams() {
return Collections.emptyList();
}
private String data;
public DataDriven(String testName, String data){
this.data = data;
}
#Test
public void test() throws AnalyzeExceptionEN{
// test data string here
}
}
}
one way is to use Junit's Enclosed runner. it's very verbose but also pretty powerful. it allows you to combine multiple different runners in one file.
other option is to use custom junit runner. for sure zohhak supports tests with parameters and without. small extract:
#RunWith(ZohhakRunner.class)
public class CoercingTest {
#TestWith("ONE_OF_ENUM_VALUES")
public void should_coerce_enum(SampleEnum param) {
assertThat(param).isEqualTo(SampleEnum.ONE_OF_ENUM_VALUES);
}
#Test
public void should_run_standard_junit_test() {
//this will also work
}
}
if it's not enough for you, for sure you can find other runners that support both kind of tests.

When using JUnit's #Parameterized, can I have some tests still run only once [duplicate]

This question already has answers here:
Excluding a non param test in parameterized test class
(9 answers)
Closed 6 years ago.
I use #Parameterized in many cases to run tests on a number of permutations. This works very well and keeps the test-code itself simple and clean.
However sometimes I would like to have some of the test-methods still run only once as they do not make use of the parameters, is there a way with JUnit to mark the test-method as "singleton" or "run-once"?
Note: This does not concern running single tests in Eclipse, I know how to do that :)
You could structure your test with the Enclosed runner.
#RunWith(Enclosed.class)
public class TestClass {
#RunWith(Parameterized.class)
public static class TheParameterizedPart {
#Parameters
public static Object[][] data() {
...
}
#Test
public void someTest() {
...
}
#Test
public void anotherTest() {
...
}
}
public static class NotParameterizedPart {
#Test
public void someTest() {
...
}
}
}
You can associate any number of test classes to run together using a suite. This way all the tests are run when you test your class and you can mix different test runners.
Create a test suite associated with the class you are testing
Add a reference to the parameterized test class
Add the other class(es) containing non parameterized tests.
import org.junit.runners.Suite;
import org.junit.runner.RunWith;
#RunWith(Suite.class)
#Suite.SuiteClasses({ParameterizedTestClass.class, UnitTests.class, MoreUnitTests.class})
public class SutTestSuite{
//Empty...
}
there is a number of junit plugins that give you some more features/power regarding parameterized tests. check zohhak, junit-parames and junit-dataprovider. they allow you to mix parametrized and simple junit tests
Before I knew about "#RunWith(Enclosed.class)" approach, I used the following (similar) solution, with inner classes extending outer class. I keep using this structure because I like that the tests are in same place and share some properties and methods and things seems clearer to me. Then, using Eclipse, in my run configuration, I choose that option "Run all tests in the selected project, package or source folder" and all these tests will be performed with just a click.
public class TestBooksDAO {
private static BooksDAO dao;
#Parameter(0)
public String title;
#Parameter(1)
public String author;
#Before
public void init() {
dao = BooksDAO.getInstancia();
}
/** Tests that run only once. */
public static class SingleTests extends TestBooksDAO {
#Test(timeout=10000)
public void testGetAll() {
List<Book> books = dao.getBooks();
assertNotNull(books);
assertTrue(books.size()>0);
}
#Test(timeout=10000)
public void testGetNone() {
List<Book> books = dao.getBooks(null);
assertNull(books);
}
}
/** Tests that run for each set of parameters. */
#RunWith(Parameterized.class)
public static class ParameterizedTests1 extends TestBooksDAO {
#Parameters(name = "{index}: author=\"{2}\"; title=\"{0}\";")
public static Collection<Object[]> values() {
return Arrays.asList(new Object[][] {
{"title1", ""},
{"title2", ""},
{"title3", ""},
{"title4", "author1"},
{"title5", "author2"},
});
}
#Test(timeout=10000)
public void testGetOneBook() {
Book book = dao.getBook(author, title);
assertNotNull(book);
}
}
/** Other parameters for different tests. */
#RunWith(Parameterized.class)
public static class ParameterizedTests2 extends TestBooksDAO {
#Parameters(name = "{index}: author=\"{2}\";")
public static Collection<Object[]> values() {
return Arrays.asList(new Object[][] {
{"", "author1"},
{"", "author2"},
{"", "author3"},
});
}
#Test(timeout=10000)
public void testGetBookList() {
List<Book> books = dao.getBookByAuthor(author);
assertNotNull(books);
assertTrue(books.size()>0);
}
}
}

issue with junit test case! avoid code duplication

I am writting jnuit test case for testing API.
my class is as follows
class MyTest extends TestCase{
List<String> argList;
public MyTest(){
//read argList from File
}
testMyTest(){
//callmy api
myApi(arg1);
}
}
Now i want make a seperate testcase for each of the 50 args.Args are read from File. I dont want to write a seperate method for calling myApi with different args.How can i do it?
I dont want to write sperate methods like
testMyTest1(){
//callmy api
myApi(arg1);
}
testMyTest1(){
//callmy api
myApi(arg2);
}
You can use a parameterized test for this.
You can use a Parameterized tests or Theories (since JUnit 4.4). For more details use
http://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit
http://blogs.oracle.com/jacobc/entry/junit_theories
private static final String[] args = new String[] {.....};
#Test
public void myTest(){
for (int i=0; i<args.length; i++){
myApi(args[i];
}
}
The above answers your question I think, however it is not good JUnit practice. It is best that each test method only invokes the method under test one time with one test condition. That way if multiple things are wrong, you get a separate error for each rather than dealing with one at a time. This would suggest the following:
private static final String[] args = new String[] {.....};
private void testMyTest(String arg){
myApi(arg);
}
#Test
public void myTest0(){
testMyTest(args[0]);
}
#Test
public void myTest1(){
testMyTest(args[1]);
}
Probably the best mechanism is to do the first option above but using the ErrorCollector rule to allow for multiple errors to be reported.
Edit I stand corrected, jordao's answer regarding parameterized tests is really the best way to do this.
Unit testing usually is made with assertions. You don't need to write a method for each argument, but execute different assertions based on your arguments.
One way for doing it would be:
class MyApiTest extends TestCase {
List<String> argList;
public MyApiTest() {}
public testMyApi() {
assertTrue(testMyApi(arg1));
assertFalse(testMyApi(arg2));
assertNull(testMyApi(arg3));
assertEquals(testMyApi(arg4), testMyApi(arg5));
}
}
I'd even prefer using annotations, like
class MyApiTest {
#Before
public setUp() {}
#After
public tearDOwn() {}
#Test
public testMyApi() {
Assert.assertTrue(testMyApi(arg1));
Assert.assertFalse(testMyApi(arg2));
Assert.assertNull(testMyApi(arg3));
Assert.assertEquals(testMyApi(arg4), testMyApi(arg5));
}
}

JUnit test with dynamic number of tests

In our project I have several JUnit tests that e.g. take every file from a directory and run a test on it. If I implement a testEveryFileInDirectory method in the TestCase this shows up as only one test that may fail or succeed. But I am interested in the results on each individual file. How can I write a TestCase / TestSuite such that each file shows up as a separate test e.g. in the graphical TestRunner of Eclipse? (Coding an explicit test method for each file is not an option.)
Compare also the question ParameterizedTest with a name in Eclipse Testrunner.
Take a look at Parameterized Tests in JUnit 4.
Actually I did this a few days ago. I'll try to explain ...
First build your test class normally, as you where just testing with one input file.
Decorate your class with:
#RunWith(Parameterized.class)
Build one constructor that takes the input that will change in every test call (in this case it may be the file itself)
Then, build a static method that will return a Collection of arrays. Each array in the collection will contain the input arguments for your class constructor e.g. the file. Decorate this method with:
#Parameters
Here's a sample class.
#RunWith(Parameterized.class)
public class ParameterizedTest {
private File file;
public ParameterizedTest(File file) {
this.file = file;
}
#Test
public void test1() throws Exception { }
#Test
public void test2() throws Exception { }
#Parameters
public static Collection<Object[]> data() {
// load the files as you want
Object[] fileArg1 = new Object[] { new File("path1") };
Object[] fileArg2 = new Object[] { new File("path2") };
Collection<Object[]> data = new ArrayList<Object[]>();
data.add(fileArg1);
data.add(fileArg2);
return data;
}
}
Also check this example
JUnit 3
public class XTest extends TestCase {
public File file;
public XTest(File file) {
super(file.toString());
this.file = file;
}
public void testX() {
fail("Failed: " + file);
}
}
public class XTestSuite extends TestSuite {
public static Test suite() {
TestSuite suite = new TestSuite("XTestSuite");
File[] files = new File(".").listFiles();
for (File file : files) {
suite.addTest(new XTest(file));
}
return suite;
}
}
JUnit 4
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
#RunWith(Parameterized.class)
public class TestY {
#Parameters
public static Collection<Object[]> getFiles() {
Collection<Object[]> params = new ArrayList<Object[]>();
for (File f : new File(".").listFiles()) {
Object[] arr = new Object[] { f };
params.add(arr);
}
return params;
}
private File file;
public TestY(File file) {
this.file = file;
}
#Test
public void testY() {
fail(file.toString());
}
}
Junit 5 Parameterized Tests
JUnit 5 parameterized tests support this by allowing the use of a method as data source:
#ParameterizedTest
#MethodSource("fileProvider")
void testFile(File f) {
// Your test comes here
}
static Stream<File> fileProvider() {
return Arrays.asList(new File(".").list()).stream();
}
JUnit 5 DynamicTests
JUnit 5 also supports this through the notion of a DynamicTest, which is to be generated in a #TestFactory, by means of the static method dynamicTest.
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import java.util.stream.Stream;
#TestFactory
public Stream<DynamicTest> testFiles() {
return Arrays.asList(new File(".").list())
.stream()
.map((file) -> dynamicTest(
"Test for file: " + file,
() -> { /* Your test comes here */ }));
}
The tests run in your IDE (IntelliJ here) will be displayed like this:
Should be possible in JUnit 3 by inheriting from TestSuite and overriding the tests() method to list the files and for each return an instance of a subclass of TestCase that takes the filename as constructor parameter and has a test method that tests the file given in the constructor.
In JUnit 4 it might be even easier.
You could consider using JUnitParams library, so you would have a few more (cleaner) options:
#org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {
#org.junit.Test
#junitparams.Parameters(method = "data")
public void test1(File file) throws Exception { }
#org.junit.Test
#junitparams.Parameters(method = "data")
public void test2(File file) throws Exception { }
public static File[] data() {
return new File[] { new File("path1"), new File("path2") };
}
}
#org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {
#org.junit.Test
#junitparams.Parameters(value = { "path1", "path2" })
public void test1(String path) throws Exception {
File file = new File(path);
}
#org.junit.Test
#junitparams.Parameters(value = { "path1", "path2" })
public void test2(String path) throws Exception {
File file = new File(path);
}
}
You can see more samples of usage here.
In addition about JUnitParams, why writting parameterized tests with it is easier and more readable:
JUnitParams project adds a new runner to JUnit and provides much
easier and readable parametrised tests for JUnit >=4.6.
Main differences to standard JUnit Parametrised runner:
more explicit - params are in test method params, not class fields
less code - you don't need a constructor to set up parameters
you can mix parametrised with non-parametrised methods in one class
params can be passed as a CSV string or from a parameters provider class
parameters provider class can have as many parameters providing methods as you want, so that you can group different cases
you can have a test method that provides parameters (no external classes or statics anymore)
you can see actual parameter values in your IDE (in JUnit's Parametrised it's only consecutive numbers of parameters)
If TestNG is an option, you could use Parameters with DataProviders.
Each individual file's test will have its result shown in the text-based report or Eclipse's TestNG plugin UI. The number of total tests run will count each of your files individually.
This behavior differs from JUnit Theories, in which all results are lumped under one "theory" entry and only count as 1 test. If you want separate result reporting in JUnit, you can try Parameterized Tests.
Test and inputs
public class FileTest {
#DataProvider(name="files")
public File[][] getFiles(){
return new File[][] {
{ new File("file1") },
{ new File("file2") }
};
// or scan a directory
}
#Test(dataProvider="files")
public void testFile(File file){
//run tests on file
}
}
Example output
PASSED: testFile(file1)
PASSED: testFile(file2)
===============================================
Default test
Tests run: 2, Failures: 0, Skips: 0
===============================================
I had a similar problem and ended up writing a simple JUnit 4 runner that allows med to dynamically generate tests.
https://github.com/kimble/junit-test-factory

Categories

Resources