简体   繁体   中英

Spy a method parameter while testing with Mockito?

Suppose that I have a class like;

public class FooBar {

    public int getMethod(List<String> code){

        if(code.size() > 100)
            throw new Exception;

            return 0;
    }
}

and I have a test class like this;

@RunWith(PowerMockRunner.class)
@PrepareForTest(FooBar.class)
public class FooBarTest{

    FooBar fooBarInstance;

    @Before
    public void setUp() {

        //MockitoAnnotations.initMocks(this);
        fooBarInstance = new FooBar();   
    }

    @Test(expected = Exception.class)
    public void testGetCorrelationListCodesParameter() {

        List<String> codes = Mockito.spy(new ArrayList<String>());
        Mockito.doReturn(150).when(codes).size();
        fooBarInstance.getMethod(codes);
    }
}

How can I make this test method to throw an exception ? I've dealing for hours to do this. Well thanks anyway.

Spying is not needed, mocking is enough. As @David said, also mocking is not needed and not recommended for value object.

Using @Test(expected = Exception.class) has many drawbacks, test can pass when exception is thrown from not expected places. Test is not working but is visible as green.

I prefer BDD style testing with catch-exception .

Reasons for using catch-exceptions

(...) in comparison to the use of try/catch blocks.

  • The test is more concise and easier to read.
  • The test cannot be corrupted by a missing assertion. Assume you forgot to type fail() behind the method call that is expected to throw an exception.

(...) in comparison to test runner-specific mechanisms that catch and verify exceptions.

  • A single test can verify more than one thrown exception.
  • The test can verify the properties of the thrown exception after the exception is caught.
  • The test can specify by which method call the exception must be thrown.
  • The test does not depend on a specific test runner (JUnit4, TestNG).
import static com.googlecode.catchexception.CatchException.caughtException;
import static com.googlecode.catchexception.apis.CatchExceptionAssertJ.*;

public class FooBarTest {

    FooBar sut = new FooBar(); // System Under Test

    @Test
    public void shouldThrowExceptionWhenListHasTooManyElements() {

        when(sut).getMethod(listWithSize(150));

        then(caughtException()).isInstanceOf(Exception.class);
    }

    private List<String> listWithSize(int size) {
        return new ArrayList<String>(Arrays.asList(new String[size]));
    }
}

Full working code for this test: https://gist.github.com/mariuszs/8543918


Not recommended solution with expected and mocking.

@RunWith(MockitoJUnitRunner.class)
public class FooBarTest {

    @Mock
    List<String> codes;

    FooBar fooBarInstance = new FooBar();

    @Test(expected = Exception.class)
    public void shouldThrowExceptionWhenListHasTooManyElements() throws Exception {

        when(codes.size()).thenReturn(150);

        fooBarInstance.getMethod(codes);

    }
}

A list is a value object. It's not something we should mock. You can write this whole test without mocking anything, if you're prepared to build a list that has a size in excess of 100.

Also, I prefer to use JUnit's ExpectedException mechanism, because it lets you check which line of the test method threw the exception. This is better than passing an argument to the @Test annotation, which only lets you check that the exception was thrown somewhere within the method.

public class FooBarTest {
    @Rule 
    public ExpectedException exceptionRule = ExpectedException.none();
    private FooBar toTest = new FooBar();

    @Test
    public void getMethodThrowsException_whenListHasTooManyElements() {
        List<String> listWith101Elements = 
            new ArrayList<String>(Arrays.asList(new String[101]));

        exceptionRule.expect(Exception.class);
        toTest.getMethod(listWith101Elements);
    }
}

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