Issue
I'm currently working on unit testing, and I'm trying to create a test testing different cases for a single function. For example, I have the following function:
public static String foo(Object arg0, Object arg1) {
String returnValue = null;
if(arg0.getName() != null && arg0.getId() != null) {
returnValue = "Value 1";
} else if (arg1.getName() != null && arg1.getId() != null ) {
returnValue = "Value 2";
}
return returnValue;
}
I want to test the following cases :
- Case 1:
arg0.getName() == null
andarg1.getName() == null
- Case 2:
arg0.getName() != null
andarg0.getId() != null
andarg1.getName() == null
- Case 3:
arg0.getName() == null
andarg1.getName() != null
andarg1.getId() != null
etc...
My current test looks like this :
public void testFoo() {
/** Setting up my mocks**/
Obj arg0 = createMock(Obj.class);
Obj arg1 = createMock(Obj.class);
/** Setting my mocks behaviors **/
// Case 1
EasyMock.expect(arg0.getName()).andReturn(null);
EasyMock.expect(arg1.getName()).andReturn(null);
// Case 2
EasyMock.expect(arg0.getName()).andReturn("Jack");
EasyMock.expect(arg0.getId()).andReturn(1);
EasyMock.expect(arg1.getName()).andReturn(null);
// Case 3
EasyMock.expect(arg0.getName()).andReturn(null);
EasyMock.expect(arg1.getName()).andReturn("Paul");
EasyMock.expect(arg1.getId()).andReturn(2);
//End Cases
EasyMock.replay(arg0_case1, arg0_case2, arg0_case3,
arg1_case1, arg1_case2, arg1_case3);
/** Testing **/
// Case 1
String expectedValue = null;
String output = foo(arg0, arg1);
assertEquals(expectedValue, output);
// Case 2
expectedValue = "Value 1";
output = foo(arg0, arg1);
assertEquals(expectedValue, output);
// Case 3
expectedValue = "Value 2";
output = foo(arg0, arg1);
assertEquals(expectedValue, output);
}
The issue I have with this test is that even if I set up my mocks for each test case, it seems that the set up fails to follow the order I choosed. I tried to add a .once()
, atLeastOnce()
, but even with that, it fails.
Do you have any solutions for this kind of test ? Maybe I should write a different test for each case ?
EDIT I found a solution, thanks to @swayamraina's solution and some modification on my code. It's not the most efficient answer, but it does the job. Here's my edited code :
public void testFoo() {
/** Setting my mocks behaviors **/
// Case 1
Obj arg0_case1 = createMock(Obj.class);
Obj arg1_case1 = createMock(Obj.class);
EasyMock.expect(arg0_case1.getName()).andReturn(null).anyTimes();
EasyMock.expect(arg1_case1.getName()).andReturn(null).anyTimes();
// Case 2
Obj arg0_case2 = createMock(Obj.class);
Obj arg1_case2 = createMock(Obj.class);
EasyMock.expect(arg0_case2.getName()).andReturn("Jack").anyTimes();
EasyMock.expect(arg0_case2.getId()).andReturn(1).anyTimes();
EasyMock.expect(arg1_case2.getName()).andReturn(null).anyTimes();
// Case 3
Obj arg0_case3 = createMock(Obj.class);
Obj arg1_case3 = createMock(Obj.class);
EasyMock.expect(arg0_case3.getName()).andReturn(null).anyTimes();
EasyMock.expect(arg1_case3.getName()).andReturn("Paul").anyTimes();
EasyMock.expect(arg1_case3.getId()).andReturn(2).anyTimes();
//End Cases
EasyMock.replay(arg0, arg1);
/** Testing **/
// Case 1
String expectedValue = null;
String output = foo(arg0_case1, arg1_case1);
assertEquals(expectedValue, output);
// Case 2
expectedValue = "Value 1";
output = foo(arg0_case2, arg1_case2);
assertEquals(expectedValue, output);
// Case 3
expectedValue = "Value 2";
output = foo(arg0_case3, arg1_case3);
assertEquals(expectedValue, output);
Like @swayamraina proposed in its answer, I created different mocks for each case test, and I add a .anyTimes()
after each EasyMock.expect().andReturn()
, and it works well.
I'll keep this post update on improvements I may implement.
Solution
Below is the updated test case
@Test
public void test() {
A arg0, arg1;
// Case 1
arg0 = EasyMock.createMock(A.class);
arg1 = EasyMock.createMock(A.class);
// expectations
EasyMock.expect(arg0.getName()).andReturn(null).once();
EasyMock.expect(arg1.getName()).andReturn(null).once();
EasyMock.replay(arg0, arg1);
// actuals
String expectedValue = null;
String output = foo(arg0, arg1);
// assertions
Assert.assertEquals(expectedValue, output);
// Case 2
arg0 = EasyMock.createMock(A.class);
arg1 = EasyMock.createMock(A.class);
// expectations
EasyMock.expect(arg0.getName()).andReturn("Jack").once();
EasyMock.expect(arg0.getId()).andReturn(1).once();
EasyMock.expect(arg1.getName()).andReturn(null).once();
EasyMock.replay(arg0, arg1);
// actuals
expectedValue = "Value 1";
output = foo(arg0, arg1);
// assertions
Assert.assertEquals(expectedValue, output);
// Case 3
arg0 = EasyMock.createMock(A.class);
arg1 = EasyMock.createMock(A.class);
// expectations
EasyMock.expect(arg0.getName()).andReturn(null).once();
EasyMock.expect(arg1.getName()).andReturn("Paul").once();
EasyMock.expect(arg1.getId()).andReturn(2).once();
EasyMock.replay(arg0, arg1);
// actuals
expectedValue = "Value 2";
output = foo(arg0, arg1);
// assertions
Assert.assertEquals(expectedValue, output);
}
Test class used:
class A {
String name; public String getName() {return name;}
Integer id; public Integer getId(){return id;}
}
Notes:
You can only replay the mocks only once. You need to create new test objects for every test case. Here, we are first creating mocks then setting expectations and replaying the mocks. Finally asserting against the actual values.
As a general process, I like to create 1 test function per unit (actual function) with . multiple test cases describing each.
Also each test case follows the below pattern
- declare variables
- describe test case
- set expectations
- define result (actual)
- apply assertions
Answered By - swayamraina
Answer Checked By - Gilberto Lyons (JavaFixing Admin)