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

@SpykBean results in NullPointerException when multiple bean candidates and none are primary #100

Closed
nmenger opened this issue Mar 9, 2023 · 2 comments

Comments

@nmenger
Copy link

nmenger commented Mar 9, 2023

When there are multiple beans defined that are the same type and none are marked @Primary, @SpykBean resolution fails with the following error:

Caused by: java.lang.IllegalStateException: Unable to register spy bean <beanclass>
	at com.ninjasquad.springmockk.MockkPostProcessor.registerSpies(MockkPostProcessor.kt:286)
	at com.ninjasquad.springmockk.MockkPostProcessor.registerSpy(MockkPostProcessor.kt:224)
	at com.ninjasquad.springmockk.MockkPostProcessor.register(MockkPostProcessor.kt:148)
	at com.ninjasquad.springmockk.MockkPostProcessor.postProcessBeanFactory(MockkPostProcessor.kt:110)
	at com.ninjasquad.springmockk.MockkPostProcessor.postProcessBeanFactory(MockkPostProcessor.kt:95)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:325)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:191)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:136)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90)
	... 75 more
Caused by: java.lang.NullPointerException
	at com.ninjasquad.springmockk.MockkPostProcessor.registerSpies(MockkPostProcessor.kt:284)
	... 89 more

This should attempt to resolve the bean by the field name when there are multiple beans with the same type and none are marked @Primary.

Found on version 3.1.1 but it appears that it is not fixed in the latest version as of today: function with error.

@jnizet
Copy link
Member

jnizet commented Mar 9, 2023

I tried to reproduce the issue with the following test case:

@SpringBootTest(classes = [MyConfig::class])
class BugTest {

    @SpykBean
    lateinit var foo1: Foo

    @Test
    fun test() {
        assertThat(foo1).isNotNull()
    }
}

@Configuration
class MyConfig {
    @Bean
    fun foo1(): Foo = Foo1()

    @Bean
    fun foo2(): Foo = Foo2()
}

interface Foo {
    fun foo(): Unit
}

open class Foo1 : Foo {
    override fun foo() {
        println("foo1")
    }
}

open class Foo2 : Foo {
    override fun foo() {
        println("foo1")
    }
}

and indeed, I get a similar stack trace.

However, the same test also fails (later, and with a better explanation) when Mockito (i.e. SpyBean) is used with the same test. And the fix is the same in both cases: you need to define the name of the bean in the SpykBean (or SpyBean) annotation:

@SpykBean(name = "foo1")
lateinit var foo1: Foo

So, I'll leave this open to make sure that I get the same error as in a Mockito test, but resolving the bean by field name won't happen because I want to do the same thing as Spring Boot.

jnizet added a commit that referenced this issue Mar 9, 2023
the way to align is not exactly the same because Spring adds null values as keys
and values of its hashmaps, but that looks wrong to me. So, rather than doing that,
I chose to avoid registering the spy if no bean name is found, which leads to the same
downstream exception

refs #100
@jnizet
Copy link
Member

jnizet commented Mar 9, 2023

I released 4.0.2 which now throws the same exception as Spring Boot in that kind of situation.

@jnizet jnizet closed this as completed Mar 9, 2023
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