title: How to mock MyBatis mapper interface?
body: <p>I am writing unit test for my Jersey rest API which uses MyBatis at the background.</p>
  
  <p>This is the structure of my classes:</p>
  
  <p><strong>rest service:</strong></p>
  
  <pre><code>@Path("/api")
  public class HelloRestService {
      @Inject
      HelloBean helloBean;
  
      @GET
      @Path("/echo/{name}")
      public Response echo(@PathParam("name") String name) {
          return Response.status(200).entity(helloBean.sayHello(name)).build();
      }
  }
  </code></pre>
  
  <p><strong>Stateless EJB:</strong></p>
  
  <pre><code>@Stateless
  public class HelloStatelessBean implements HelloBean {
      // Injected MyBatis mapper (dao)
      @Inject
      private EmployeeMapper employeeMapper;
  
      @Override
      public Employee getEmployeeById(final Long id) {
          return employeeMapper.getEmployeeById(id);
      }
  
      @Override
      public ArrayList&lt;Employee&gt; getEmployee() {
          return employeeMapper.getAllEmployee();
      }
  
      /**
       * Echo.
       */
      @Override
      public String sayHello(String name) {
          return String.format("Hello %s! This is Ejb :)", name);
      }
  }
  </code></pre>
  
  <p><strong>MyBatis mapper interface:</strong></p>
  
  <pre><code>@Dependent
  @Mapper
  public interface EmployeeMapper {
      @Select("select * from EMPLOYEE where id = #{id}")
      Employee getEmployeeById(Long id);
  
      @Select("select * from EMPLOYEE")
      ArrayList&lt;Employee&gt; getAllEmployee();
  }
  </code></pre>
  
  <p>I have a nice junit test for testing my MyBatis mapper. It works fine. The next step is that I would like to write a test for my jersey rest class. This is what I have:</p>
  
  <pre><code>public class HelloRestServiceTest extends JerseyTest {
      @Override
      public Application configure() {
          enable(TestProperties.LOG_TRAFFIC);
          enable(TestProperties.DUMP_ENTITY);
  
          return new ResourceConfig(HelloRestService.class) {
              {
                  register(new HelloStatelessBean());
                  register(Mockito.mock(EmployeeMapper.class));
              }
          };
      }
  
      @Test
      public void echo() throws Exception {
          Response response = target("/api/echo/John").request().get();
          Assert.assertEquals(200, response.getStatus());
          Assert.assertNotNull(response.getEntity());
      }
  }
  </code></pre>
  
  <p>But this test throws an exception: </p>
  
  <pre><code>org.glassfish.jersey.internal.inject.Providers checkProviderRuntime
  WARNING: A provider a.b.HelloStatelessBean registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider a.b.HelloStatelessBean will be ignored. 
  org.glassfish.jersey.internal.inject.Providers checkProviderRuntime
  WARNING: A provider a.b.EmployeeMapper$$EnhancerByMockitoWithCGLIB$$ee86c913 registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider a.b.EmployeeMapper$$EnhancerByMockitoWithCGLIB$$ee86c913 will be ignored.
  A MultiException has 1 exceptions.  They are:
  1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EmployeeMapper,parent=HelloStatelessBean,qualifiers={},position=-1,optional=false,self=false,unqualified=null,52451302)
  MultiException stack 1 of 1
  org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EmployeeMapper,parent=HelloStatelessBean,qualifiers={},position=-1,optional=false,self=false,unqualified=null,52451302)
  </code></pre>
  
  <p>What is the proper way to mock MyBatis mapper with mockito?</p>
  
  <hr>
  
  <p>UPDATE 1
  EJB test works like a charm:</p>
  
  <pre><code>@RunWith(MockitoJUnitRunner.class)
  public class HelloStatelessBeanTest {
  
      private static SqlSessionFactory sqlSessionFactory;
  
      @Spy
      private HelloBean helloBean = new HelloStatelessBean();
  
      @Test
      public void sayHello() throws Exception {
  
          String actual = helloBean.sayHello("Pear");
          System.out.println(actual);
      }
  
      @Test
      public void testGetEmployeeById() {
          // create an SqlSessionFactory
          try (Reader reader = Resources.getResourceAsReader("mybatis-configuration.xml")) {
  
              sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
              SqlSession sqlSession = sqlSessionFactory.openSession();
              EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
              Employee employee = mapper.getEmployeeById(1l);
              Assert.assertNotNull(employee);
              Assert.assertNotNull(employee.getId());
  
          } catch (Exception e) {
              throw new RuntimeException(e);
          }
      }
  }
  </code></pre>
  
  <p><strong>But it does not work with jersey. I have tried it this way, but I get same exception then before:</strong></p>
  
  <pre><code>public class HelloRestServiceTest extends JerseyTest {
      @Override
      public Application configure() {
          enable(TestProperties.LOG_TRAFFIC);
          enable(TestProperties.DUMP_ENTITY);
  
          return new ResourceConfig(HelloRestService.class) {
              {
                   try (Reader reader = Resources.getResourceAsReader("configuration.xml")) {
                       SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                       SqlSession sqlSession = sqlSessionFactory.openSession();
                       EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
  
                       register(new HelloStatelessBean());
                       register(mapper, EmployeeMapper.class);
                   } catch (Exception e) {
                       throw new RuntimeException(e);
                   }
              }
          };
      }
  
      @Test
      public void echo() throws Exception {
          Response response = target("/api/echo/Arnold").request().get();
          Assert.assertEquals(200, response.getStatus());
          Assert.assertNotNull(response.getEntity());
      }
  }
  </code></pre>
  
  <p>Any idea?</p>