如何用Arquillian(PART2)模拟MyBatis映射器接口? [英] How to mock MyBatis mapper interface with Arquillian (PART2)?

查看:119
本文介绍了如何用Arquillian(PART2)模拟MyBatis映射器接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我第二次尝试使用MyBatis创建集成测试.我已经尝试了很多方法,但是似乎没有解决该问题的方法.希望你们能帮助我.

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.

在我之前的问题中我试图编写一个集成测试来检查我的其余API的输出.场景如下:rest API调用注入的EJB,该EJB使用MyBatis执行一些SQL:rest api> ejb> mybatis.不幸的是,我既无法注入,也无法模拟MyBatis映射器接口,因此我的测试无法进行:(

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 :(

现在,我创建了另一个测试方案,但最终遇到了同样的情况. 现在,我的场景非常简单:我有一个带有注入的MyBatis映射器的EJB.我想在带有Arquillian的嵌入式Glassfish/Payara服务器中进行测试.

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.

这是我的例外:

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";
    }
}

帐户映射器(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);
}

我的测试班:

@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());
    }
}

如果我注释了AppleBeanTest中的两行内容以消除对MyBatis映射器的厌倦,那么我的测试就可以正常工作.

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

我也将源代码上传到了github.

解决方案

我的测试中缺少以下课程. @blackwizard谢谢您使我朝正确的方向前进.

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);
        }
    }
}

git项目已更新.

推荐答案

现在,我没有资源来克隆和运行您的项目以确认我要说的话.但是,如果需要的话,我将在星期一进行讨论,与此同时,以下可能是一个轨迹:

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:

我认为它不起作用,因为缺少了一些非常重要的内容:SqlSessionFactory.

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

mybatis-cdi doc 在第一段中指出:

SqlSessionFactory是任何MyBatis bean的源,因此首先 需要创建一个(至少),并让容器知道 存在.

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.

实际上,如果没有会话,则没有理由获取Mapper实例.如果@Mapper注释足够,则它只能提供一个空的shell,因为它不能链接到任何基础数据源. 然后,如果没有Mapper,则无法将其注入到EJB中,这就是Weld抱怨的.

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.

部署成功后,是否使用@Inject private AccountDao accountDao?我不明白为什么Weld会允许不进行任何注射.但是,如果是这样,请检查accountDao值(调试断点或日志).

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).

这篇关于如何用Arquillian(PART2)模拟MyBatis映射器接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆