Java 在Mockito中替换数据源

Java 在Mockito中替换数据源,java,junit,mocking,jndi,mockito,Java,Junit,Mocking,Jndi,Mockito,我有在Jboss服务器上执行查询的代码。它具有基于JNDI的数据源,如下所示: public class JNDIBasedDao { DataSource dataSource; public JNDIBasedDao(){ try { InitialContext ic = new InitialContext(); dataSource = (DataSou

我有在Jboss服务器上执行查询的代码。它具有基于JNDI的数据源,如下所示:

    public class JNDIBasedDao {

        DataSource dataSource;

        public JNDIBasedDao(){

            try {
                InitialContext ic = new InitialContext();
                dataSource = (DataSource) ic.lookup("java://bla-bla-bla");
            } catch (NamingException e) {
            e.printStackTrace();
            }


        }

public class Manager {

    public Manager(){}

    private JNDIBasedDao dao = new JNDIBasedDao();

    public void runOperation(){
        this.dao.executeInsert();
    }
在我的笔记本电脑上,我没有Jboss,也无法连接到这个服务器,我想在HSQLDB上运行单元测试

我想基于HSQLDB从ApacheCommons创建BasicDataSource,并将此对象注入JNDibasedAO

@Mock
BasicDataSource dataSource = new BasicDataSource();

@Mock 
JNDIBasedDao dao = new JNDIBasedDao();

@InjectMocks
Manager manager = new Manager();
@Before
    public void initMocks(){
        dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
        dataSource.setUrl("jdbc:hsqldb:mem:dannyTest");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
        dataSource.setInitialSize(5);
        dataSource.setMaxActive(10);
        dataSource.setPoolPreparedStatements(true);
        dataSource.setMaxOpenPreparedStatements(10);

        MockitoAnnotations.initMocks(this);

    }

    @Test
    public void testRunOperartion() {
        manager.runOperartion();
    }

但我仍然得到JNDI错误。能做到吗?请提供帮助。

@injectmock将只执行setter注入

在Manager类中更改以下内容

private JNDIBasedDao dao = new JNDIBasedDao();

void setDao(JNDOBasedDao dao)
{
   this.dao = dao;
}

您可以创建第二个构造函数并注入InitialContext

public class JNDIBasedDao {
  DataSource dataSource;

  public JNDIBasedDao() {
    this(new InitialContext());
  }

  public JNDIBasedDao(InitialContext ic) {
    try {
      dataSource = (DataSource) ic.lookup("java://bla-bla-bla");
    } catch (NamingException e) {
      e.printStackTrace();
    }
  }

  ....
}

现在您可以提供一个模拟的InitialContext,它提供了您的数据源。

因为您使用的是
@Mock
,所以不需要通过调用它们的构造函数来实际实例化这些对象

而不是:

@Mock
BasicDataSource dataSource = new BasicDataSource();

@Mock 
JNDIBasedDao dao = new JNDIBasedDao();
尝试:

并让Mockito处理这些类的模拟版本的创建

当然,当您这样做时,您会得到这些类的Mock版本,因此在您的数据源上调用所有这些方法将导致调用默认的Mockito存根…而这些存根不起任何作用

不确定您为什么将
@Mock
与对同一对象的方法调用组合在一起,看起来您希望得到一个结果


可能单步执行调试器,并在引发异常时检查正在使用的对象的运行时类。它们可能不是您期望的样子。

您不想模拟DAO而不是数据源有什么特别的原因吗?在最新版本中,@InjectMocks也进行字段注入。见:
@Mock
BasicDataSource dataSource = new BasicDataSource();

@Mock 
JNDIBasedDao dao = new JNDIBasedDao();
@Mock
BasicDataSource dataSource;

@Mock 
JNDIBasedDao dao;