Skip to content

MockBean does not resolve the right type for abstract test class #20916

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

Closed
onacit opened this issue Apr 11, 2020 · 6 comments
Closed

MockBean does not resolve the right type for abstract test class #20916

onacit opened this issue Apr 11, 2020 · 6 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@onacit
Copy link

onacit commented Apr 11, 2020

Please forgive me if this kind of issue is not appropriate. I already SO-ed.

Just in cases of issue titles, this issue might have a same issue with #15969. I'm not sure.

I have a tightly coupled abstract service class with generic types.

I have an abstract service class which autowires a specific type of repository.

@NoRepositoryBean
interface SomeRepository<T> { }

abstract class SomeService<T extends SomeRepository<U>, U ...> {

    @Autowired
    private U repositoryInstance;
}

Now I'm trying to create an abstract test class for subclasses of the service class.

@SpringBootTest
abstract class SomeServiceTest<T extends SomeService<U>, U extends SomeRepository<V>, V ...> {

    @Autowired
    private T serviceInstance;

    // personally expected
    // to mock the serviceInstance.repositoryInstance, and it doesn't.
    @MockBean
    private U repositoryInstance; // != serviceInstance.repositoryInstance();
}

But mocking the bean in a test class of actual service class works.
(Which is I intended that extended modules don't have to do.)

class OtherServiceTest
        extends SomeServiceTest<OtherService, OtherRepository, ...> {

    @TestConfiguration
    OtherServiceTestConfiguration {

        // WORKS!!!
        // == serviceInstance().repositoryInstance();
        @MockBean private OtherRepository repositoryInstance;
    }
}

class AnotherServiceTest
        extends SomeServiceTest<AnotherService, AnotherRepository, ...> {

    // WORKS!!!
    // == serviceInstance().repositoryInstance();
    @MockBean private AnotherRepository repositoryInstance;
}

Is there any intrinsic mechanism for mocking the SomeServiceTest#serviceIntance.repositoryInstance?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 11, 2020
@mbhave
Copy link
Contributor

mbhave commented Apr 14, 2020

This might be happening because the mock is created for the SomeRepository type instead of the actual type which is OtherRepository or AnotherRepository.

@onacit Just to be sure, could you provide a minimal sample that we can run to reproduce the issue?

@mbhave mbhave added the for: team-attention An issue we'd like other members of the team to review label Apr 14, 2020
@onacit
Copy link
Author

onacit commented Apr 15, 2020

@mbhave Thank you. I managed to create a simplest and reproducible project from my original code base.

https://github.com/onacit/spring-boot-issue20916

There is only one @Test method there in an abstract class and there are two actual test classes inherit.

  • ...some0.SomeProductRepositoryServiceTest which passes.
  • ...some1.SomeProductRepositoryServiceTest which fails.

@mbhave
Copy link
Contributor

mbhave commented Apr 28, 2020

Thanks for the sample @onacit. I have taken a look and it seems like a bug to me. It is marked for: team-attention which means we will discuss it on one of the weekly team calls.

@philwebb philwebb self-assigned this May 13, 2020
@philwebb philwebb added type: bug A general bug and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels May 13, 2020
@philwebb philwebb added this to the 2.2.x milestone May 13, 2020
@mbhave mbhave self-assigned this May 19, 2020
@mbhave mbhave changed the title MockBean applying in abstract test class? MockBean not resolving the right type for abstract test class Jun 11, 2020
@mbhave mbhave changed the title MockBean not resolving the right type for abstract test class MockBean does not resolve the right type for abstract test class Jun 18, 2020
@mbhave mbhave closed this as completed in 615cf63 Jun 18, 2020
@mbhave mbhave modified the milestones: 2.2.x, 2.2.9 Jun 18, 2020
wilkinsona added a commit that referenced this issue Jul 27, 2020
The fix for gh-20916 updated DefinitionsParser so that the
ResolvableType for each MockBean or SpyBean field included the
implementation class from which the field was found. Where the field
was declared with a variable generic signature that was made constant
by its implementation class, this allowed the correct concrete type to
be determined. It also had the unintended side-effect of preventing two
test classes with identical `@MockBean` and `@SpyBean` configuration
from sharing a context as the resolvable types for their mock and spy
bean fields would now be different.

This commit updates DefinitionsParser to only include the
implementation class in the ResolvableType if the field's generic type
is variable. For cases where it is not variable, this restores the
behaviour prior to the fix for gh-20916.

Fixes gh-22566
@Xyaren
Copy link

Xyaren commented Aug 28, 2020

Could this be backported to 2.2.x ?
We would really appreciate that, as we are still relying on Elasticsearch Jest, that is not included in 2.3.x anymore.

@wilkinsona
Copy link
Member

@Xyaren The fix was made in 2.2.9.

@Xyaren
Copy link

Xyaren commented Aug 28, 2020

I'm sorry, picket I got confused between two issues. Thanks for the quick response!

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

No branches or pull requests

6 participants