How to mock MyBatis mapper interface with Arquillian (PART2)?

♀尐吖头ヾ 提交于 2020-01-07 04:19:26

问题


This is my 2nd try to create integration test with MyBatis. I have tried many things but it seems that there is no solution for this issue. Hope that you guys can help me.

In my previous question I tried to write an integration test to check the output of my rest API. The scenario there was the following: rest API calls an injected EJB which executes some SQL with MyBatis: rest api > ejb > mybatis. Unfortunately I was not able neither to inject, nor mock MyBatis mapper interface so my test does not work :(

Now I created another test scenario but I ended up in a same situation. Now my scenario is crazy easy: I have an EJB with an injected MyBatis mapper. I would like to test it within an embedded Glassfish/Payara server with Arquillian.

This is my exception:

org.glassfish.deployment.common.DeploymentException: CDI deployment failure:WELD-001408: Unsatisfied dependencies for type AccountDao with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private a.b.c.AppleBean.accountDao
  at a.b.c.AppleBean.accountDao(AppleBean.java:0)

EJB:

@Stateless
public class AppleBean {
    @Inject
    private AccountDao accountDao;

    public String say() {
        return "Apple";
    }
}

Account maper (DAO):

@Mapper
public interface AccountDao {

    @Select("SELECT * FROM account WHERE id = #{id}")
    @Results({
            @Result(property = "email", column = "email", javaType = String.class),
            @Result(property = "firstName", column = "first_name", javaType = String.class),
            @Result(property = "lastName", column = "last_name", javaType = String.class),
    })
    Account findById(@Param("id") Long id);
}

My test class:

@RunWith(Arquillian.class)
public class AppleBeanTest {
    @EJB
    private AppleBean bean;

    @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap
                .createFromZipFile(WebArchive.class, new File("target/war-demo-test-1.0.war"))
                .addPackages(true, "a.b");
    }

    @Test
    public void say() throws Exception {
        assertNotNull(bean);
        System.out.println(bean.say());
    }
}

If I comment the two lines in AppleBeanTest to remove the refelence to MyBatis mapper then my test works fine.

I uploaded the source code to github as well.


SOLUTION

The following class was missing from my test. @blackwizard thank you for putting me to the right direction.

SessionFactoryProducer.java

@ApplicationScoped
public class SessionFactoryProducer {
    @ApplicationScoped
    @Produces
    @SessionFactoryProvider
    public SqlSessionFactory produce() throws Exception {
        SqlSessionFactory sessionFactory;
        try (Reader reader = Resources.getResourceAsReader("mybatis.xml")) {
            sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        }
        // create sample table
        //createTable(sessionFactory);

        return sessionFactory;
    }

    private void createTable(final SqlSessionFactory manager) throws Exception {
        try (SqlSession session = manager.openSession()) {
            LOGGER.info("-> Initializing database...");
            Connection conn = session.getConnection();
            Reader reader = Resources.getResourceAsReader("create-table-postgresql.sql");
            ScriptRunner runner = new ScriptRunner(conn);
            runner.runScript(reader);
            reader.close();
            LOGGER.info("=> Database has been initialized properly.");
        } catch (Exception ex) {
            LOGGER.error("Error executing SQL Script...", ex);
        }
    }
}

The git project is updated.


回答1:


Here and now, I have not resources to clone and run your project to confirm what I will say. But I will on Monday if necessary and in the meantime, the following may be a track:

I think it does not work because something very important is missing: the SqlSessionFactory.

mybatis-cdi doc states in the first paragraph:

The SqlSessionFactory is the source of any MyBatis bean so first you need to create one (at least) and let the container know about it existence.

Indeed, there is no reason to obtain a Mapper instance if there is no Session. if @Mapper annotation was sufficient, it could only provide an empty shell because not link to any underlying datasource. Then if there is no Mapper, it cannot be injected into the EJB, that's what Weld complains about.

When deployment succeeds, is it with the @Inject private AccountDao accountDao? I don't see why Weld would allow injecting with nothing. But if it does, check accountDao value (debug break point or log).



来源:https://stackoverflow.com/questions/42728129/how-to-mock-mybatis-mapper-interface-with-arquillian-part2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!