Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling getExceptionTypes() on concrete object that is used as interface doesn't return exception types from interface #2201

Closed
henrykuijpers opened this issue Feb 11, 2021 · 2 comments

Comments

@henrykuijpers
Copy link

henrykuijpers commented Feb 11, 2021

org.mockito.internal.stubbing.answers.InvocationInfo#isValidException is doing validation on the exception types that can be thrown from this method.

In my codebase, I'm programming against an interface, but in fact, a spy is created from an instance that is implementing the interface, that drops the exception types that that implementation does not throw. However, the code that is calling the interface is of course unaware of that fact. Also, that implementation is a mock implementation (a real mock implementation, not a Mockito mock()/spy() instance).

A testcase here:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.exceptions.base.MockitoException;
import org.mockito.junit.jupiter.MockitoExtension;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;

@ExtendWith(MockitoExtension.class)
public class MockitoExceptionTypesIssue {
    @Test
    void exceptionTypeIoExceptionShouldBeMockableForObjectBeingSpyedOn() {
        final I x = spy(new C());
        final IOException ioException = new IOException("Oh my god!");
        final MockitoException e = assertThrows(
                MockitoException.class,
                () -> doThrow(ioException)
                        .when(x)
                        .m());
        assertEquals("\n" +
                "Checked exception is invalid for this method!\n" +
                "Invalid: " + ioException,
                e.getMessage()
        );
    }

    interface I {
        void m() throws IOException;
    }

    static class C implements I {
        public void m() {
            // no-op
        }
    }
}
@shreelakshmijoshi
Copy link

Hi @TimvdLippe !
I am a new open source contributor and would love to solve this issue, could you help me understand the issue better by providing some extra references ?
Is this is issue open to contribute ?

@harshit181
Copy link

harshit181 commented Aug 29, 2021

isn't it expected behavior?
From the user perspective , it look like that method can throw super method exception but from code perspective it is limited to exception of object created.
As we are spying on the object and method in that object is just throwing the sub Exception ,the code knows that it will throw only sub Exception and not exception implemented by super method .

the same issue(?) will happen when mocking a class with interface /parent class with additional method exception .

From the implementation perspective
As we are mocking /spying on the object of sub class ,the mockito only knows about the method and class being mocked ,not the reference class/interface ,so not sure if anything can be done even if this is considered as a bug

final I x = new C();
x.getClass() ; // it will return C ,not I 

andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 23, 2022
…hen parent contains throws keyword on its method and child overrides this method removing throws, it should be possible to mock throwing exception from child
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 23, 2022
…hen parent contains throws keyword on its method and child overrides this method removing throws, it should be possible to mock throwing exception from child
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 23, 2022
…hen parent contains throws keyword on its method and child overrides this method removing throws, it should be possible to mock throwing exception from child
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 23, 2022
…hen parent contains throws keyword on its method and child overrides this method removing throws, it should be possible to mock throwing exception from child
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 26, 2022
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 26, 2022
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 26, 2022
andrey-kozel pushed a commit to andrey-kozel/mockito that referenced this issue Jan 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants