Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EasyMock and modifing a mutable method parameter

How does one use EasyMock to modify a mocked method's mutable method parameter?

For example, I have class that uses a BlockingQueue. I want to mock the BlockingQueue member for unit testing. My class calls the method queue.drainTo(Collection c). Calling this method removes elements from the queue and adds them to the collection. How would I mock this behavior using EasyMock? Examples would be great.

like image 439
Nathan Reese Avatar asked Aug 25 '10 19:08

Nathan Reese


People also ask

Which of the given method is used to create EasyMock?

The expect() method tells EasyMock to simulate a method with certain arguments. The andReturn() method defines the return value of this method for the specified method parameters. The times() method defines how often the Mock object will be called. The replay() method is called to make the Mock object available.

How does EasyMock capture work?

EasyMock has a feature called Capture which allows us to capture the arguments with which mocks are called, such that we can verify the argument values after having exercised the object being tested.

What is EasyMock replay?

The replay method is used to pass the mock from recording (where you record the method you expect to be called) to replaying state (where you actually test).


1 Answers

You can use andAnswer and getCurrentArguments:

public void testDrainToQueue() {
  BlockingQueue<Foo> queue = EasyMock.createMock(BlockingQueue.class);
  EasyMock.expect(queue.drainTo(EasyMock.isA(List.class)))
      .andAnswer(new IAnswer<Integer>() {
        public Integer answer() {
          ((List) EasyMock.getCurrentArguments()[0]).add(new Foo(123));
          return 1; // 1 element drained
        }
      });
  EasyMock.replay(queue);
  ...
}

It sometimes helps to extract a helper class or method:

private static IAnswer<Integer> fakeDrainReturning(final List drainedElements) {
  return new IAnswer<Integer() {
    @Override public Integer answer() {
      ((List) EasyMock.getCurrentArguments()[0]).addAll(drainedElements);
      return drainedElements.size();
    }
  };
}

Then you can do:

List<Foo> drainedElements = Arrays.asList(new Foo(123), new Foo(42));
EasyMock.expect(queue.drainTo(EasyMock.isA(List.class)))
    .andAnswer(fakeDrainReturning(drainedElements));

It might be better to use a real BlockingQueue and find a way to insert the desired value into the queue before the method that you expect to remove data from the queue.

like image 184
NamshubWriter Avatar answered Sep 24 '22 08:09

NamshubWriter