使用Mockito进行测试时间谍方法参数?

时间:2014-01-21 15:46:06

标签: java unit-testing junit mockito

假设我有类似的课程;

public class FooBar {

    public int getMethod(List<String> code){

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

            return 0;
    }
}

我有一个像这样的测试类;

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

如何使此测试方法抛出异常?我已经花了好几个小时才能做到这一点。非常感谢,无论如何。

2 个答案:

答案 0 :(得分:4)

不需要间谍活动,嘲笑就足够了。正如@David所说,不需要进行模拟,也不建议使用值对象。

使用@Test(expected = Exception.class)有许多缺点,当从非预期的位置抛出异常时,测试可以通过。测试无效但显示为绿色。

我更喜欢使用catch-exception进行BDD样式测试。

Reasons for using catch-exceptions

  

(...)与使用try / catch块相比。

     
      
  • 测试更简洁,更易于阅读。
  •   
  • 缺少断言不能破坏测试。假设您忘记在预期会抛出异常的方法调用后面键入fail()。
  •   
     

(...)与捕获和验证异常的测试运行程序特定机制相比较。

     
      
  • 单个测试可以验证多个抛出的异常。
  •   
  • 测试可以在捕获到异常后验证抛出异常的属性。
  •   
  • 测试可以指定必须通过哪个方法调用抛出异常。
  •   
  • 测试不依赖于特定的测试运行器(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]));
    }
}

此测试的完整工作代码:https://gist.github.com/mariuszs/8543918


不建议使用expected解决方案并进行模拟。

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

    }
}

答案 1 :(得分:2)

列表是值对象。这不是我们应该嘲笑的东西。如果你准备构建一个大小超过100的列表,你可以编写整个测试而不需要嘲笑任何东西。

另外,我更喜欢使用JUnit的ExpectedException机制,因为它可以让你检查测试方法的哪一行引发了异常。这比将参数传递给@Test注释更好,只允许您检查在方法中的某处抛出异常。

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