I am new to JUnit and facing difficulty in writing JUnit.
I have an interface and a class
Interface
public interface Student{
List<String> getStudentList();
void setStudentList(List<String> studentList);
void createStudentList();
}
Class
public class StudentServiceImpl implements Student{
private List<String> studentList
public List<String> getStudentList() {
return studentList;
}
public void setStudentList(final List<String> studentList){
this.studentList = studentList;
}
public void createStudentList(){
if (studentList == null) {
studentList = new ArrayList<String>();
studentList.add("John");
studentList.add("Bill");
studentList.add("Ricky");
studentList.add("Jack");
}
setStudentList(studentList);
}
}
What is the best to write Junit for above class. What should be kept in mind while writing JUnit cases. Can somebody help me?
Here is an example of IMHO well-written test case (written in notepad, please correct if does not compile):
import static org.fest.assertions.Assertions.assertThat;
public class StudentTest {
private final Student student = new StudentServiceImpl();
#Test
public void shouldReturnEmptyListOfStudentsWhenNotInitialized() {
//given
//when
List<String> students = student.getStudentList();
//then
assertThat(students).isEmpty();
}
#Test
public void shouldReturnSomeStudentsWhenListCreated() {
//given
student.createStudentList();
//when
List<String> students = student.getStudentList();
//then
assertThat(students).containsExactly("John", "Bill", "Ricky", "Jack");
}
#Test
public void shouldStorePreviouslySetListOfStudents() {
//given
student.setStudentList(Arrays.asList("Jane", "Bob"));
//when
List<String> students = student.getStudentList();
//then
assertThat(students).containsExactly("Jane", "Bob");
}
}
Few tips:
Keep tests short and simple
Test name should describe what use case is being tested
Separate setup code, tested logic and assertions
Code should be easy to read. Use fluent and descriptive libraries like FEST
Further improvements:
The first test should fail, do you know why?
There are still few tests missing, do you know which ones?
Related
I am trying to find the way to test RichFilter function just like RichMappFunction like present here : RichMapFunction Testing is present here......Searched through internet and find nothing...Please help...
public class Person{
public String name;
public Int age;
}
public class OCRKafkaFilter extends RichFilterFunction<Person> {
#Override
public boolean filter(Person person) {
return person.age>21;
}
}
How can we write a test case for this rich filter function for stateful operators ...
You can up a test harness for a filter function doing something like this:
private OCRKafkaFilter function;
private OneInputStreamOperatorTestHarness<Person, Person> harness;
#BeforeEach
void setUpHarness() throws Exception {
function = new OCRKafkaFilter();
StreamFilter<Person> operator = new StreamFilter<>(function);
harness = new OneInputStreamOperatorTestHarness<>(operator);
harness.open();
}
In the example you gave, the RichFilterFunction isn't stateful. In that case you can write tests like this:
public class FilterFunctionTest {
#Test
public void testFilter() {
OCRKafkaFilter filter = new OCRKafkaFilter();
Person person21 = new Person(21);
Person person22 = new Person(22);
assertEquals(false, filter.filter(person21));
assertEquals(true, filter.filter(person22));
}
}
I have the following scenario:
I perform several tests (#Test) and tests in Cucumber, in Selenium Webdriver, Java.
The tests are going well. However, I want to leave a string stored in one #Test (public void) in another #Test (public void). I cannot.
Could anyone help?
First test:
#Test
public void testDocuments() {
OneClass oneClass = new OneClass();
oneClass.one();
oneClass.two();
}
Second test:
#Test
public void testDocuments() {
OneClass oneClass = new OneClass();
oneClass.one();
oneClass.two();
}
Method one
public String one() {
if (this.cnpj == null) {
this.cnpj = add.cnpj(false);
} else {
}
return this.cnpj;
}
Both tests I want you to use the same generated string !!!!
I look forward and thanks in advance!
I'm not sure what your method one() does, but assuming you want to use the same value for two different tests, why not just do this:
OneClass oneClass = new OneClass();
String yourGeneratedString = oneClass.one();
// First test
#Test
public void testDocuments() {
yourFunction(yourGeneratedString);
}
// Second test
#Test
public void testDocuments2() {
yourOtherFunction(yourGeneratedString);
}
If I understand correctly, you need this.cnpj value to be available within the second test?
Each time you do new OneClass() , it creates a new instance of it.
So you can do one of the following:
Use singleton instance of OneClass
Make cnpj a static field within OneClass
If I understand it right, you want to share data from one test to second one. If you user testNG then you can do it this way.
import org.testng.ITestContext;
import org.testng.annotations.Test;
public class MyTest {
#Test
public void testOne(ITestContext context){
context.setAttribute("myKey", "myValue");
}
#Test
public void testTwo(ITestContext context){
String valueFromTestOne = (String) context.getAttribute("myKey");
System.out.println("My key = " + valueFromTestOne);
}
}
Simple question, I have a class with have a List field with Items, I have a method operating on that List, checking if there is a Item with a name given in parameter and returning true or false. I would like to test that method, creating an ArrayList in test class, mocking JdbcItemDao class, and calling a method. Method in test cannot reach an array, how to fix it? Code:
public class JdbcItemDao {
private List<Item> tempStockList;
public JdbcItemDao() {
this.tempStockList = getAllStockItems();
//getting items from my sql, returning them as ArrayList
}
public boolean checkStockItems(String itemName) {
for (Item item : tempStockList) {
if (item.getItemName().equalsIgnoreCase(itemName)) {
return true;
}
}
return false;
}}
Test class:
public class JdbcTest {
JdbcItemDao jdbcItemDao;
List<Item> tempStockList;
#Before
public void setup() {
jdbcItemDao = mock(JdbcItemDao.class);
tempStockList = new ArrayList<>();
tempStockList.add(new Item(1, "LEDTv", new BigInteger("40"),
new Integer("3"), new BigInteger("70")));
}
#Test
public void checkStockItemsName() throws Exception {
assertTrue(jdbcItemDao.checkStockItems("LEDTv"));
}}
If you cannot refactor i guess your left with creating a private class, overriding the method and using that class for testing:
public class JdbcTest {
List<Item> tempStockList = new ArrayList<>();
#Before
public void setup() {
tempStockList = new ArrayList<>();
tempStockList.add(new Item(1, "LEDTv", new BigInteger("40"),
new Integer("3"), new BigInteger("70")));
}
#Test
public void checkStockItemsName() throws Exception {
JdbcItemDao jdbcItemDao = new CustomJdbcItemDao();
assertTrue(jdbcItemDao.checkStockItems("LEDTv"));
}
private class CustomJdbcItemDao extends JdbcItemDao{
#Override
public List<Item> getAllStockItems(){
return tempStockList;
}
}
}
You use the wrong kind of test double. You need a spy (which is a wrapper around the real implementation) instead of a mock (which is a subclass overriding all methods of the mocked class):
jdbcItemDao = spy(new JdbcItemDao());
tempStockList = new ArrayList<>();
tempStockList.add(new Item(1, "LEDTv", new BigInteger("40"),
new Integer("3"), new BigInteger("70")));
doReturn(tempStockList).when(jdbcItemDao).getAllStockItems();
Off cause this only works if you move
this.tempStockList = getAllStockItems();
out of the constructor...
There is a method 'getAllStockItems', it is in JdbcItemDao.java class
public List<Item> getAllStockItems() {
return jdbcTemplate.query(SELECT_ALL_STOCK_ITEMS, itemRowMapper);
}
It is getting a data from MySQL database, so that's why i would like to use fake Array in tests.
#RunWith(JUnitParamsRunner.class)
public class MySimpleTest {
private MyRec rec;
private Matrix matrix;
#Before
public void createRecognizerBeforeEveryExecution() {
rec = new MyRec();
matrix = MatrixUtils.createMatrixWithValues();
}
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[]{"expectedvalue1", "input1"},
new Object[]{"expectedvalue2", "input2"}
);
}
#Test
#Parameters(method = "data")
public void test1(String output, String input) {
rec.fun1(matrix);
assertEquals(output, rec.someFunction(input));
}
public static Iterable<Object[]> data2() {
return Arrays.asList(
new Object[]{"expectedothervalue1", "input1"},
new Object[]{"expectedothervalue2", "input2"}
);
}
#Test
#Parameters(method = "data2")
public void test2(String output, String input) {
rec.fun1(matrix);
rec.fun2(matrix);
assertEquals(output, rec.someFunction(input));
}
}
I'm trying to find out what is the proper way to make this test. I'd like to use parametrized test, because it's really convenient way.
So as you can see, in every test function I call some function (fun1 and fun2). But I need to call it only once per every test (e.g. before each parametrized test execution).
Is there any way to tell JUnitParams that it should execute other function before executing all of parametrized tests?
I can't use #Before annotation, because as you can see in test1 I'm not using fun2. It think it should be executed by separate function.
Solution 1:
As fun[1|2] does not depend on internal test state, try to place their invocations inside data and data2 methods accordingly.
public static Iterable<Object[]> data() {
rec.fun1(matrix);
return Arrays.asList(
new Object[]{"expectedvalue1", "input1"},
new Object[]{"expectedvalue2", "input2"}
);
}
public static Iterable<Object[]> data2() {
rec.fun1(matrix);
rec.fun2(matrix);
return Arrays.asList(
new Object[]{"expectedvalue1", "input1"},
new Object[]{"expectedvalue2", "input2"}
);
}
Solution 2:
Spliting test cases is not a best practice. Your test are harder to maintain. Flow is far more complicated. There is also a risk your tests start depends on each other. Duplication in tests sometimes is simply better.
PS:
If you are using Strings as test method parameters it's better to pass them exactly like in 25th line of this file:
https://github.com/Pragmatists/JUnitParams/blob/master/src/test/java/junitparams/usage/SamplesOfUsageTest.java instead of special methods.
#Test
#Parameters({"AAA,1", "BBB,2"})
public void paramsInAnnotation(String p1, Integer p2) { }
I decided to use TestNG to resolve this problem (code just to show my train of thought):
import org.testng.Assert;
import org.testng.annotations.*;
import java.lang.reflect.Method;
public class TempTest {
private Integer number;
#BeforeMethod
public void init(Method m) {
number = 5;
switch(m.getName()) {
case "test2":
fun(10);
fun2(5);
break;
case "test1":
fun(10);
break;
}
}
public void fun(int value) {
number += value;
}
public void fun2(int value) {
number -= value;
}
#Test
public void test1() {
Assert.assertEquals(new Integer(15), number);
}
#Test
public void test2() {
Assert.assertEquals(new Integer(10), number);
}
#Test
public void test3() {
Assert.assertEquals(new Integer(5), number);
}
}
Imagine I have the following class structures:
public interface Sender {
void send(String note);
}
public interface Agent {
void sendNote(String note);
}
public class Emailer implements Sender {
void send(String note) {
//...do something
}
}
public class Helper {
List<String> populateNotes() {
//...do something
}
}
public class EmailAgent implements Agent {
List<String> notes;
void sendNote(String note) {
Helper helper = new Helper();
notes = helper.populateNotes();
for (String s : notes) {
Sender sender = new Emailer();
sender.send(s);
}
}
}
Now, I want to unit test the sendNote() method in EmailAgent. However, there is a dependency on Helper as it needs to populate the list notes. If in the JUnit test I first call populateNotes() before calling sendNote()...
Is this a unit test or acceptance test?
Or should I hard coded the list?
Or use suggestion 2 - create a stub producing a hard-coded list - then unit test the sendNote method. Mocking would also help with this but requires coding against interfaces to be of any use. While it will work, a simple stub should also do the trick.