JUnit - Test class instantiation with objects in parameters - java

I am very new to JUnit testing and I am trying to understand how to test the instantiation of an class.
Let us say that I have the following ToyBox class which needs an ArrayList<Toy> in order to be instantiated. This list of toys is created on another part of the program, of course, but I do not understand very well where I should create it in order to unit test ToyBox.
ToyBox Class
public ToyBox(ArrayList<Toy> toyList){
this.toys= toyList;
for (Toy toy: toyList) {
checkToy(toy);
}
}
private void checkToy(Toy toy){
if (toy.isRed()){
this.numRed += 1;
} else {
this.numBlue += 1;
}
}
public int getBlues(){
return this.numBlue;
}
ToyBoxTest
public class ToyBoxTest {
#Test
public void getNumBlues() throws Exception {
// assert that num blues corresponds
}
Where should I instantiate the ToyBox class in order to perform the getNumBlues() method?
Should it be like this?
public class ToyBoxTest {
ArrayList<Toy> toyList = new ArrayList<Toy>();
Toy toy1 = new Toy("blue", "car");
Toy toy2 = new Toy("red", "bike");
toyList.add(toy1);
toyList.add(toy2);
#Test
public void getNumBlues() throws Exception {
// assert that num blues corresponds
ToyBox box = new ToyBox(toyList);
assertEquals(1, box.getBlues());
}
Basically, my question is where and how should I create the arraylist of objects needed to test a class that depends on that created list.

Most tutorials will state that the best practice is to instantiate the object you're about to test in a setup method (a #Before method in JUnit's terminology). However, your usecase doesn't fit this pattern well. As your constructor holds all the logic, you should instantiate the object in the test itself, and then assert that getNumBlues() and getNumReds() return the correct results. E.g.:
#Test
public void bothColors() throws Exception {
ArrayList<Toy> toyList = new ArrayList<>(Arrays.asList
new Toy("blue", "car"),
new Toy("red", "bike"));
ToyBox box = new ToyBox(toyList);
assertEquals(1, box.getBlues());
}
#Test
public void justBlues() throws Exception {
ArrayList<Toy> toyList = new ArrayList<>(Arrays.asList
new Toy("blue", "car"),
new Toy("blue", "bike"));
ToyBox box = new ToyBox(toyList);
assertEquals(2, box.getBlues());
}
// etc...

Related

Mock local variable in Junit, Mockito

I'm working on a test case for a code using Mockito. The code looks like this,
public class Example {
#Autowired
private HelperService hs;
public void someMethod() {
List<String> names = new ArrayList<>();
hs.addValues(names);
if(names.size() < 5) {throw new RuntimeException("Invalid names list");}
return;
}
}
public class HelperService {
public void addValues(List<String> names) {
names.add("alex");
names.add("harry");
names.add("james");
names.add("maria");
names.add("bob");
}
}
I know this is a contrived example but I have a similar usecase where I cannot modify the existing code. I want to unit test the Example class using Junit, Mockito. How can I test the exception scenario where names.size() is < 5.
I'm going to assume you already have a means for setting the HelperService field in your test (whether that's by making it a #SpringBootTest, using #InjectMocks, or something else). So this will just give options for providing one that will let you do what you want:
Extend HelperService and inject that:
// Inject this into your class under test
private HelperService hs = new LessThan5NameAddingHelperService();
class LessThan5NameAddingHelperService extends HelperService {
#Override
public void addNames( List<String> names ) {
names.add( "Dave" );
}
}
Provide a mock HelperService which does the same:
// Inject this into your class under test
private HelperService hs;
#Before
public void setupMockHelperService() {
hs = mock( HelperService.class );
doAnswer( invocation -> {
List<String> names = ( List<String> ) invocation.getArguments()[0];
names.add( "Dave" );
return null;
} ).when( hs ).addNames( any() );
}

Split Into Lists based on Object, without instanceof

Im going to go straight to the point.
I got 3 classes. Person, Professor and Student. (Persona, Profesor, Alumno).
Both professor and student extends from Person. But Person can also be instantiated, because it's not abstract.
I have 50 persons, randomly generated on a list. It can be any kind, person professor or student.
I want to separate them each into a different list.
At the moment, I did this:
for(Persona persona : personas) {
if(persona instanceof Profesor) {
profesores.add((Profesor) persona);
}
else if(persona instanceof Alumno) {
alumnos.add((Alumno) persona);
}
else {
nuevasPersonas.add(persona);
}
}
profesores is a list of Professor
alumnos is a list of Students
nuevasPersonas is a list of Persons
Which works perfect. But I was told not to use instanceof, so I don't get used to it.
Any ideas on how to separate them into lists, without the use of instanceof?
Thanks.
I would use instanceof, why wouldn't you want to get used to it?
Anyway, an alternative could be having a variable type (with getter, but no setter), in Person (=0), and override it to 1 and 2 in Professor and Student.
Then,you would test the variable instead of using instanceof.
Perhaps your teacher wants you to create an overriden method which answers the question isStudent or isProfessor?
However, since this gives us no extra information that is not already available via the instanceof operator, this is a contrived example where adding these redundant methods is not really a great design decision. Unfortunately in beginner classes you will sometimes encounter such contrived examples which are overly simplified for the purpose of teaching a particular language concept.
You can overload an "add" method with each of the object types - something like the following code.
The main method just adds instances of three different Objects to the ObjectSplitter class - it separates them out in to different Collections
public class ObjectSplitter {
public static void main(String ... args){
ObjectSplitter d = new ObjectSplitter();
d.addToCollection(new Object1());
d.addToCollection(new Object1());
d.addToCollection(new Object2());
d.addToCollection(new Object1());
d.addToCollection(new Object1());
d.addToCollection(new Object1());
d.addToCollection(new Object2());
d.addToCollection(new Object3());
d.addToCollection(new Object1());
System.out.println("Num Ob1s : " + d.getOb1sSize());
System.out.println("Num Ob2s : " + d.getOb2sSize());
System.out.println("Num Ob3s : " + d.getOb3sSize());
}
private List<Object1> ob1s = new ArrayList<>();
private List<Object2> ob2s = new ArrayList<>();
private List<Object3> ob3s = new ArrayList<>();
void addToCollection(Object1 o){
ob1s.add(o);
}
void addToCollection(Object2 o){
ob2s.add(o);
}
void addToCollection(Object3 o){
ob3s.add(o);
}
int getOb1sSize(){
return ob1s.size();
}
int getOb2sSize(){
return ob2s.size();
}
int getOb3sSize(){
return ob3s.size();
}
static class Object1 {
}
static class Object2 extends Object1 {
}
static class Object3 extends Object2 {
}
}
also you can use getClass().getSimpleName() as below:
public static void main (String[] args) throws java.lang.Exception
{
List<Test1> list = new ArrayList<>(2);
Test1 o1 = new Test1();
list.add(o1);
Test2 o2 = new Test2();
list.add(o2);
for (Test1 test : list) {
System.out.println(test.getClass().getSimpleName());
}
}
static class Test1{
}
static class Test2 extends Test1{
}
in the for loop you can have a if condition as like as below code to do your job:
for (Test1 test : list) {
String className = test.getClass().getSimpleName();
if(className.equals("Test1")) {
System.out.println("Test1");
} else if(className.equals("Test2")) {
System.out.println("Test2");
}
System.out.println();
}
another solution according to overriding methods is:
public static void main (String[] args) throws java.lang.Exception
{
List<Test1> list = new ArrayList<>(2);
Test1 o1 = new Test1();
list.add(o1);
Test2 o2 = new Test2();
list.add(o2);
for (Test1 test : list) {
test.addToMyTypeList();
}
for(Test1 test : Test1.list) {
System.out.println(test.getClass().getSimpleName());
}
for(Test1 test : Test1.list) {
System.out.println(test.getClass().getSimpleName());
}
}
static class Test1{
public static List<Test1> list = new ArrayList<>();
public void addToMyTypeList() {
String className = test.getClass().getSimpleName();
if(className.equals("Test1")) {
Test1.list.add(this);
}
}
}
static class Test2 extends Test1{
public static List<Test1> list = new ArrayList<>();
#Override
public void addToMyTypeList() {
String className = test.getClass().getSimpleName();
if(className.equals("Test2")) {
Test2.list.add(this);
}
}
}

Mocking a DAO in Mockito

I'm just getting into testing of code. I have done unit tests before but haven't really isolated them. So they were more like integration test (indirectly). I want to give Mockito a try and I have added it to my Intellij IDE.
But I have no idea of how to actually implement mocking at all. There are examples on their website but I just can't wrap my head around the concept of mocking. I know that one uses mocking to isolate the unit testing to ensure that the errors are in the unit itself and not in a dependency.
I wrote the following:
#Test
public void testChangeMemberReturnsTrue() throws Exception {
Member tempMem = new Member();
tempMem.setMemberFirstName("Swagrid");
tempMem.setMemberLastName("McLovin");
tempMem.setMemberID("SM666");
SQLDUMMY.saveMember(tempMem); //Save member to dummy DB.
Member checkMem = new Member();
ArrayList<Member> memArr = SQLDUMMY.getAllMembers();
for (Member m : memArr) { // Look through all saved members
if (m.equals(tempMem)) { // If match, save to checkMem
checkMem = m;
}
}
assertTrue(tempMem.equals(checkMem)); // Make sure they are really equal.
String newfirstname = "Darius";
String newlastname = "DunkMaster";
assertTrue(memhandling.changeMember(tempMem, newfirstname, newlastname));
}
And here is the actual method:
public boolean changeMember(Member mem, String n1, String n2) {
try {
ArrayList<Member> memArr = SQLDUMMY.getAllMembers();
for (Member m : memArr) {
if (m.equals(mem)) {
m.setMemberFirstName(n1);
m.setMemberLastName(n2);
m.setMemberID(ensureUniqueID(m, m.getMemberID())); //Just a method call to another method in the same class to ensure ID uniqueness.
return true;
}
else {
return false;
}
}
}
catch (Exception e) {
System.out.println("Error4.");
}
return false;
}
I'd like to mock the SQLDUMMY (Which I created just to see if my tests would pass at all, which they do.) The SQLDUMMY class looks like this:
public class SQLDUMMY {
private static ArrayList<Member> memberList = new ArrayList<>();
private static ArrayList<Ship> shipList = new ArrayList<>();
public static ArrayList<Member> getAllMembers() {
return memberList;
}
public static void saveMember(Member m) {
memberList.add(m);
}
public static void deleteMember(Member memIn) {
memberList.remove(memIn);
}
public static void saveShip(Ship newShip) {
shipList.add(newShip);
}
public static ArrayList<Ship> getAllShips() {
return shipList;
}
public static void deleteShip(Ship s) {
shipList.remove(s);
}
}
It basically just consists of getters and add/remove for the ArrayLists that act as a contemporary DB storage.
Summary: How can I mock the SQLDUMMY class (DAO), so it is no longer a dependency for the Unit tests?
You need to read on how Mockito works.
The basic idea is that it extends you class and and overrides all methods and allows you to return what ever you want it too.
Syntax is :
SQLDummy sqlDummy = Mockito.mock(SQLDummy.class);
Mockito.when(sqlDummy.getAllShips()).thenReturn(new ArrayList< Ship >())

Java - HashCode - Equals

I have a problem with Unit Tests in Java.
I put here my code and my error. On internet I found this is a problem with hashcode. I need to recreate them but I don't know why and how.
My method :
public void setGroupModel(GroupModel groupModel) {
this.groupModel = groupModel;
this.groupModel.add(this);
}
cellControler file :
public class CellController {
public void click(CellModel cellModel, HexModel hexModel)
{
GroupModel groupModel = new GroupModel();
cellModel.setGroupModel(groupModel);
hexModel.getGridContentModel().getArrayListGroupModel().add(groupModel);
}
}
My UnitTest :
public class CellControllerTest {
protected CellController cellController;
#Before
public void setUp() throws Exception {
cellController = new CellController();
}
#After
public void tearDown() throws Exception{
}
#Test
public void testClick() throws Exception{
GroupModel groupModel = new GroupModel();
CellModel cellModel = new CellModel();
HexModel hexModel = new HexModel(); // hexModel has an attribute : gridContentModel
cellController.click(cellModel, hexModel);
assertEquals(groupModel, cellModel.getGroupModel());
}
}
My error
java.lang.AssertionError: expected:<model.GroupModel#6d5380c2> but was:<model.GroupModel#45ff54e6>
I think the problem is : this.groupModel = groupModel;
What I have to write and why? :)
To compare is easy, you need to override hashCode and equals or use a comparator, if you did not do that then the message you get is perfectly normal.
Here you set the groupModel AND modify the groupModel.
public void setGroupModel(GroupModel groupModel) {
this.groupModel = groupModel;
this.groupModel.add(this); // the modification
}
In your test you compare the groupModel you just created and the groupModel that you get from cellModel.getGroupModel(), but that one has been modified, so the two objects are different
assertEquals(groupModel, cellModel.getGroupModel());

Injecting class fields in Java

Hello all
I have a piece of software that I would like to run many different times, each for a particular value of a class field that is set in the class's constructor.
E.g, somewhere in the code is something along the lines of
public class Stuff
{
private double importantVal;
public Stuff(double val)
{
this.importantval = val;
}
public double doStuff()
{
return 4 * importantVal;
}
}
This class and method is very far down in the program/call-stack, so I can't merely call doStuff several times by itself.
I would like to test the program for various values of importantVal, perhaps by placing them in a file and iterating over them. I worked out the easy bit of running the program many times , but I have no good idea of how to substitute different values of importantVal. If all else fails I can always write a script that modifies the source code, but that feels ugly and ad-hoc. Is there a more elegant solution involving injection, or something along those lines?
To illustrate what the folks are trying to tell you here, here's how the testcases might look like:-
public class StuffTest {
#Test
public void testDoStuff_Zero(){
Stuff stuff = new Stuff(0);
assertEquals(0, stuff.doStuff());
}
#Test
public void testDoStuff_One(){
Stuff stuff = new Stuff(1);
assertEquals(4, stuff.doStuff());
}
#Test
public void testDoStuff_NegativeValue(){
Stuff stuff = new Stuff(-10);
assertEquals(-40, stuff.doStuff());
}
#Test
public void testDoStuff_PositiveValue(){
Stuff stuff = new Stuff(10);
assertEquals(40, stuff.doStuff());
}
#Test
public void testDoStuff_DecimalValue(){
Stuff stuff = new Stuff(1.1);
assertEquals(4.4, stuff.doStuff());
}
}
public class StuffRunner {
public static void main(String[] args) {
double x = 0.0d;
for (int i = 0; i < 100; ++i) {
Stuff s = new Stuff(x);
if (s.doStuff() != 4 * x) {
System.out.print("Error, unexpected value. X=");
System.out.println(x);
}
x = x + 1.22;
}
}
}
do you have multiple instances of the Stuff class? if not, perhaps you could try "injecting" the values by making importantVal static? or to inject multiple values use a List?
public class Stuff{
private static List<Double> testVals = new LinkedList()<Double>;
private double importantVal;
public Stuff(double val)
{
this.importantval = val;
}
public static addTest(double test){
testVals.add(test);
}
public double doStuff()
{
return 4 * testVals.removeFirst();
}
}

Categories

Resources