Brian
Brian

Reputation: 2425

Simulating side effects of a mocked method

I have a method in a class that causes side effects to the method's parameter:

public void SideEffectsClass {
    public void doSomethingWithSideEffects(List<Object> list) {
        // do something to the list
    }
}

And this class being tested:

public void ClassUnderTest() {
   public List<Object> execute() {
       List<Object> results = new ArrayList<Object>();
       new SideEffectsClass().doSomethingWithSideEffects(results);
       return results;
   }
}

My test method using JMockit:

@Test
public void test() throws Exception
{
    // arrange
    new Expectations()
    {
        SideEffectsClass sideEffects;
        {
            new SideEffectsClass();
            sideEffects.doSomethingWithSideEffects((List<Object>) any);
            // I want to simulate that the List<Object> parameter has changed 
            // (has more elements, less elements, etc. after this method is called
        }
    };

    // act
    ClassUnderTest testClass = new ClassUnderTest();
    List<Object> results = testClass.execute();

    // assert
    Assert.assertEquals(myExpectedResults, results);
}

Upvotes: 2

Views: 2160

Answers (2)

Rog&#233;rio
Rog&#233;rio

Reputation: 16390

You can use a Delegate object to change an argument value:

    sideEffects.doSomethingWithSideEffects((List<Object>) any);
    result = new Delegate() {
        void delegate(List<Object> list) { list.add(new Object()); }
    };

If all you need is to verify that the doSomethingWithSideEffects methods was called, then the test could be written more simply as:

@Test
public void test(final SideEffectsClass sideEffects)
{
    List<Object> results = new ClassUnderTest().execute();

    assertEquals(myExpectedResults, results);

    new Verifications() {{
        sideEffects.doSomethingWithSideEffects((List<Object>) any);
    }};
}

Upvotes: 4

Ryan Stewart
Ryan Stewart

Reputation: 128899

As the test is trying to tell you, the side effects aren't part of the behavior of ClassUnderTest. Don't try to test that here. Based on the code you're showing, all you should be testing is that results is passed to doSomethingWithSideEffects() and that the same object is returned from execute(). Being unfamiliar with JMockit syntax, I can't tell you exactly how to write it.

Aside: I do recommend, however, that everyone using a tool like jMock, JMockit, or EasyMock should use Mockito instead if they can.

Upvotes: 0

Related Questions