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.

David Diehl
  • 225
  • 1
  • 3
  • 11
  • Could you provide a [MCVE](https://stackoverflow.com/help/minimal-reproducible-example) like [these](https://github.com/harawata/mybatis-issues) ? I'm not so sure if I could answer, but it would help people who are willing to help, I believe. – ave Jun 17 '20 at 12:04
  • I understand. I see if I can get this created in the next few days. Thanks for the advice. – David Diehl Jun 18 '20 at 22:16
  • Ok, I created that project here: https://github.com/dldiehl77/mybatis-issues/tree/master/so-62409666 – David Diehl Jul 09 '20 at 19:14
  • 4
    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. – ave Jul 10 '20 at 18:34
  • Okay, I think I found a fix. Could you report this as a bug on the [tracker](https://github.com/mybatis/spring-boot-starter/issues/new) when you have some spare time? If you're busy, please just let me know and I'll take care of it later. Thanks! – ave Jul 10 '20 at 19:10
  • 1
    Sure thing. I am creating the issue there now. thanks for investigating this. https://github.com/mybatis/spring-boot-starter/issues/475 – David Diehl Jul 11 '20 at 02:46

1 Answers1

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;
bbarke
  • 309
  • 1
  • 14
  • 2
    You should try the new version [2.1.4](https://github.com/mybatis/spring-boot-starter/releases/tag/mybatis-spring-boot-2.1.4). :) – ave Nov 14 '20 at 21:10
  • 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. – pro- learner Dec 24 '21 at 01:52
  • @ave 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. – Patan Nov 07 '22 at 12:21