简体   繁体   中英

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);
}

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);
    }};
}

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.

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