0

I'm currently implementing a few repository methods as @Async with spring-boot, and it's working like it should when i actually boot up the application, but when running integration tests, things starts to act weird.

I have setup a little project that showcases the problem.

Repository:

interface MyObjectRepository : CrudRepository<MyObject, Long> {

    @Async
    fun findBySomething(something: String): ListenableFuture<MyObject?>

}

Application:

@SpringBootApplication
@EnableAsync
class Application {

    private val log = LoggerFactory.getLogger(Application::class.java)

}

fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}

And my test case:

@RunWith(SpringRunner::class)
@DataJpaTest
class MyObjectRepositoryTest {

    @Autowired
    lateinit var target: MyObjectRepository

    @Before
    fun `init`() {
        target.deleteAll()
    }

    @Test
    fun `should be able to find MyObject`() {
        val m = MyObject("something")
        val expected = target.save(m)

        val futureResult = target.findBySomething("something")
        val result = futureResult.get()

        assert.that(result, equalTo(expected))
    }
}

My results:

expected == the object (good)

result == null (bad)

If i enable @Async on class-level on the repository, the result gets flipped around.

And if i further make the test sleep after calling target.save(m) both expected and result are null

Anyone have any suggestions as to what could be wrong? Am i missing something (like an annotation for testing purposes?).

Again, everything is working fine when i boot up the application, and make rest-calls to my controller.

Martin Hansen
  • 2,033
  • 1
  • 18
  • 34

1 Answers1

0

I would suggest not using @DataJpaTest as you are wanting to test another component with Spring along with the JPA repository.

Spring Boot slice tests, like @WebMvcTest, @JsonTest etc. only load up a slice of the application context, not the entire thing. They load only specific auto-configurations, and certain test dependencies too. Which I would guess are missing when using @DataJpaTest

I would suggest using @SpringBootTest although this too can be pretty heavy weight as it loads, the vast majority, of the application.

Darren Forsythe
  • 10,712
  • 4
  • 43
  • 54
  • That make the result become something. Although now the assert still fails with equality (i have not implemented a custom equals method yet, but this wasn't a problem with the `@DataJpaTest` annotation, running without `@Async`). With a simple `println()` i can tell the objects has the same properties. I will continue to fiddle with it with the `@SpringBootTest` instead, as its closer to a permanent solution atm. – Martin Hansen Aug 10 '17 at 11:06
  • Update: the equality fail has to do with hibernate's `PersistentBag`, since my production code has a list of objects as a field. When using `@DataJpaTest` the type is `ArrayList` and with `@SpringBootTest` it's `PersistentBag`. (couldn't edit my other answer) – Martin Hansen Aug 10 '17 at 11:26