简体   繁体   中英

How to mock a method which is called by another method using EasyMock?

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

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM