Throwing exceptions from Mockito mock

16,868

Please could you check that the compiler really is complaining about a RuntimeException?

The thing about RuntimeException is that it shouldn't matter at compile time. I suspect the compiler is actually complaining about MyException - which I presume is a checked exception, noticed by the compiler, which is thrown by the doSomething() method. You should be able to simply add the throws MyException to the test method, which will then be caught by the test runner. Since it's expected, the test runner will pass.

Share:
16,868
DaveyBob
Author by

DaveyBob

Updated on June 29, 2022

Comments

  • DaveyBob
    DaveyBob almost 2 years

    Something tells me I'm doing something wrong...it shouldn't be this hard.

    I have a class that relies on some inner class. I'm creating that inner through a protected method so that I can override that in a test to provide a mock. I understand that to get a Mockito mock object to throw an exception from a void method, I have to use doThrow.

    But my problem is that the compiler complains that the call to Mockito.doThrow() is throwing RuntimeException...so then I have to add a throws clause to the method setting up the mock. Is that a bug in Mockito itself? doThrow is declaring something that should happen in the future, but not during the setup of the mock.

    My OuterClass looks like...

    public class OuterClass {
      protected InnerClass inner;
      protected void createInner() { inner = new InnerClass(); }
      protected doSomething() {
        try {
          inner.go();
        } catch (RuntimeException re) {
          throw new MyException("computer has caught fire");
        }
      }
    }
    

    And my test code looks like...

    @Test(expected = MyException.class)
    public void testSomething() {
      OuterClass outer = new TestOuterClass();
      outer.doSomething();
    }
    
    public static class TestOuterClass extends OuterClass {
      @Override
      public void createInner() {
        InnerClass mock = Mockito.mock(InnerClass.mock);
        Mockito.doThrow(new RuntimeException("test")).when(mock).go();  // PROBLEM
        inner = mock;
      }
    }
    
  • DaveyBob
    DaveyBob about 13 years
    Yeah, my mistake. What it's really complaining about is MyException, as you suggested. InnerClass.go() is declared to throw MyException (I left that out in my code above). But OuterClass.createInner() does not. I think it's not the Mockito.doThrow() that's causing the problem...it's the call to .go() on the end that's doing it. So even though @test method already declares throws MyException, this doesn't help.
  • DaveyBob
    DaveyBob about 13 years
    Ah ha! I figured it out. I just need to wrap my doThrow...go() stuff in a try/catch to hide it from the create method. But when the create method is called, it does actually call the mock, and it does get and trap the RuntimeException.