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

Missing TypeVariable in TypeBaseCandidateFilter from version 5.2 #3093

Open
Bezmenny opened this issue Aug 15, 2023 · 1 comment
Open

Missing TypeVariable in TypeBaseCandidateFilter from version 5.2 #3093

Bezmenny opened this issue Aug 15, 2023 · 1 comment

Comments

@Bezmenny
Copy link

Bezmenny commented Aug 15, 2023

Hi,

I am currently migrating our project from spring-boot 2 to spring-boot 3 and with that I recieved mockito 5.3.1. I tried also mockito 5.4, but it contains same code and therefore behaves exactly same.

By merge #2921 you have introduced some type checking during filtering in TypeBaseCandidateFilter. Unfortunatelly for us (or me specifically, since it is my task to do migration), in mentioned type checking is missing check for type TypeVariable.

Currently TypeBaseCandidateFilter has method isCompatibleTypes, which looks like this:

protected boolean isCompatibleTypes(Type typeToMock, Type mockType, Field injectMocksField) {
        boolean result = false;
        if (typeToMock instanceof ParameterizedType) {
            if (mockType instanceof ParameterizedType) {
                if (typeToMock.equals(mockType)) {
                    result = true;
                } else {
                    ParameterizedType genericTypeToMock = (ParameterizedType)typeToMock;
                    ParameterizedType genericMockType = (ParameterizedType)mockType;
                    Type[] actualTypeArguments = genericTypeToMock.getActualTypeArguments();
                    Type[] actualTypeArguments2 = genericMockType.getActualTypeArguments();
                    result = this.recurseOnTypeArguments(injectMocksField, actualTypeArguments, actualTypeArguments2);
                }
            } else {
                Class<?> concreteMockClass = (Class)mockType;
                Stream<Type> mockSuperTypes = this.getSuperTypes(concreteMockClass);
                result = mockSuperTypes.anyMatch((mockSuperType) -> {
                    return this.isCompatibleTypes(typeToMock, mockSuperType, injectMocksField);
                });
            }
        } else if (typeToMock instanceof WildcardType) {
            WildcardType wildcardTypeToMock = (WildcardType)typeToMock;
            Type[] upperBounds = wildcardTypeToMock.getUpperBounds();
            result = Arrays.stream(upperBounds).anyMatch((t) -> {
                return this.isCompatibleTypes(t, mockType, injectMocksField);
            });
        } else if (typeToMock instanceof Class && mockType instanceof Class) {
            result = ((Class)typeToMock).isAssignableFrom((Class)mockType);
        }
        return result;
    }

In our case, we have situation similar to the small project I prepared:
MockitoMissingTypeVariable.zip

Result of test in this small projeckt and our project is that @InjectMock does nothing and NullPointerException is thrown.

As I mentioned above, I think that adding new else if into isCompatibileTypes method would be sufficient.

@nineninesevenfour
Copy link

@Bezmenny I downloaded your example (thank you for providing it!) and found this is just another one that would be fixed by #3123 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants