MockBean and MyBatis Mapper not working together (as they did before Spring Boot 2.2.7)
Asked Answered
D

1

6

I am using MyBatis Spring Boot Starter version 2.1.3. Ever since moving to Spring Boot 2.2.7 (I've also tried 2.2.8 and 2.3.1 with the same results), I've had a problem using the MockBean annotation to mock a MyBatis interface (e.g. DAO). Let's say I have an interface like this one:

@Mapper
@Repository
public interface OrderDAO {
   int insertOrder(@Param("order") Order order);
}

I'd like to execute an integration test and mock this mapper within my OrderService that contains a field of type OrderDAO.

My integration test is annotated with @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) and contains this field:

@MockBean
private OrderDAO orderDAO;

When I run a test such as this and look at what the references to the OrderDAO objects are, in my integration test I see this:

com.example.dao.OrderDAO$MockitoMock$1819884459

But inside my OrderService class the field is this:

com.sun.proxy.$Proxy179 (org.apache.ibatis.binding.MapperProxy@37d9310e)

So, calls to Mockito.verify obviously don't work because my mock has not been injected into my OrderService class. Now, very oddly, I found that adding this code makes everything work:

@TestConfiguration
static class MockConfig {
    @Bean
    public OrderDAO orderDAO() {
        return Mockito.mock(OrderDAO.class);
    }
}

Adding this nested class along with adding the ContextConfiguration annotation on the integration test class, and now the object that gets injected into the OrderService class is the MockitoMock -- the same object that is referenced by the MockBean annotated field in the test class. I didn't have to do this with Spring Boot 1.2.6 and earlier and I couldn't find any reference to a change that would have caused this (although perhaps I didn't search long enough).

So, I am wondering if I am doing something incorrectly, or, am I missing something I should be doing? It seems like this should just work like it did before, which the need for this extra nested TestConfiguration class. Appreciate any insights anyone can provide. Thanks.

Digestion answered 16/6, 2020 at 13:27 Comment(6)
Could you provide a MCVE like these ? I'm not so sure if I could answer, but it would help people who are willing to help, I believe.Gawky
I understand. I see if I can get this created in the next few days. Thanks for the advice.Digestion
Ok, I created that project here: github.com/dldiehl77/mybatis-issues/tree/master/so-62409666Digestion
I have found a workaround. The test passes if the bean name is specified explicitly i.e. @MockBean(name = "userDAO"). I'm still investigating if there is a proper fix in MyBatis side.Gawky
Okay, I think I found a fix. Could you report this as a bug on the tracker when you have some spare time? If you're busy, please just let me know and I'll take care of it later. Thanks!Gawky
Sure thing. I am creating the issue there now. thanks for investigating this. github.com/mybatis/spring-boot-starter/issues/475Digestion
C
4

As mentioned by ave in the comments, I had to add the name to the mock bean annotation to get it to work

@MockBean(name = "orderDAO")
private OrderDAO orderDAO;
Coates answered 10/11, 2020 at 17:22 Comment(3)
You should try the new version 2.1.4. :)Gawky
Faced same issue recently while upgrading from Spring boot 2.2.1 Release version to 2.5.1. Naming the MockBean worked out of the box.Lelia
@Gawky I am unable to mock Mapper beans. I am getting error Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required. Can you let me know if any thing can be done to fix.Vantage

© 2022 - 2024 — McMap. All rights reserved.