Reputation: 99
I need to mock a method inside a void method.
Here is my sample code:
class MyClass {
public MyClass(Session s, Boolean b1, Boolean b2)
void myMethod(some paramaters...) {
// some code
int count= setSize();
}
int setSize() {
// some calculation....
return size;
}
Now in my test class I want to mock setSize()
to return my own value say 300
.
I did like:
MyClass mockclass = createNiceMock(MyClass.class);
EasyMock.expect(mockimplyZero.setBatchSize()).andReturn(Integer.valueOf(300));
mockclass.myMethod(parameters....)
when call myMethod
, it's not going properly into the method.
I think it might be EasyMock is setting default values to the MyClass
constructor. How to do the mock correctly?
There are no methods in MyClass
except constructor, myMethod
and setSize
Upvotes: 3
Views: 5774
Reputation: 140407
You should not mock one method while testing another method on the same class. You could theoretically do that (using a Mokito spy for example).
In that sense, you are approaching this on a wrong level: you actually should not care which other methods your method under test calls within your class under test. But if you have to adapt things for testing, then the way to go would be (for example) a method that allows your test code to setup that size field prior invoking mymethod()
.
Or: you separate concerns, and move that "size" part into its own class X. And then your class under test could hold an instance of X; and that instance could then be mocked.
Long story short: you want to step back and read some tutorials on how to use EasyMock. This not something that you can learn by trial and error.
Upvotes: 1
Reputation: 5711
You can do it using partial mocking. Here is an example close to your code.
First the tested class. You will need to create a partial mock of it. getSize
should be mocked, but myMethod
should since it is the tested method.
Also, frequently, you will want to call a constructor to initialize the class correctly (a classical mock won't call any constructor).
class MyClass {
private boolean b1;
private boolean b2;
public MyClass(boolean b1, boolean b2) {
this.b1 = b1;
this.b2 = b2;
}
int myMethod() {
return getSize();
}
int getSize() {
return 42;
}
public boolean getB1() {
return b1;
}
public boolean getB2() {
return b2;
}
}
The test will then be the following
import org.junit.Test;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
public class MyClassTest {
@Test
public void test() {
// Create a partial mock by calling its constructor
// and only mocking getSize
MyClass mock = createMockBuilder(MyClass.class)
.withConstructor(true, true)
.addMockedMethod("getSize")
.createMock();
// Record that getSize should return 8 (instead of 42)
expect(mock.getSize()).andReturn(8);
// All recording done. So put the mock in replay mode
replay(mock);
// Then, these assertions are to prove that the partial mock is
// actually doing what we expect. This is just to prove my point. Your
// actual code will verify that myMethod is doing was is expected
// 1. Verify that the constructor was correctly called
assertEquals(true, mock.getB1());
assertEquals(true, mock.getB2());
// 2. Verify that getSize was indeed mocked
assertEquals(8, mock.myMethod());
// Check everything expected was indeed called
verify(mock);
}
}
Job done. Note that this isn't necessarily a sign of bad design. I frequently use it when testing the Template method pattern.
Upvotes: 2