如何使用 EasyMock 模拟在测试 class 中实例化的 classes?

How to Mock classes that are being instantiated within the test class with EasyMock?

我正在尝试测试一个有点复杂的程序。 getDatesMi 在同一个 class 中调用一个方法。该方法进行调用 return 转换为 MarketLimits 类型的查询结果的接口方法。

我正在使用 EasyMock 和 junit。

我的问题是:

  1. 如何测试 getSqlMapClientTemplate().queryForObject ?
  2. 如何模拟 getSqlMapClientTemplate().queryForObject 的结果被转换为 MarketLimits

我是 java 和 EasyMock 的新手,所以答案可能很明显,但不胜感激。

我目前在 subDates.greaterThenOne()

上收到 NullPointerException

MyServiceDao 的接口

import com.foo.bar.domain.MarketLimits;

public interface MyServiceDao {
    public MarketLimits getDates(long orgId) throws DataAccessException;
}

class 实现了 MyServiceDao

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.foo.bar.domain.MarketLimits;


public class myServiceImpl implements MyServiceDao{

    @Override
    public MarketLimits getDates(long orgId) throws DataAccessException {
        return (MarketLimits) getSqlMapClientTemplate().queryForObject("retrieveLimits", orgId);
    }

}

主要class测试中

import com.foo.bar.dao.MyServiceDao;

public class myServiceImpl extends reports implements myService {

    @Autowired
    private MyServiceDao myServiceDao;


    public String getDatesMi() throws Exception {
        MarketLimits subDates = getDates(23);

        System.out.print(subDates);  // this prints out null

        if(subDates.greaterThenOne()){
            // do some things
        }

        return "result"
    }


    @Override
    public MarketLimits getDates(long orgId) {
        return myServiceDao.getDates(orgId);
    }


    public setMyServiceDao(MyServiceDao myServiceDao){
        this.myServiceDao = myServiceDao
    }

}

我的测试

@RunWith(EasyMockRunner.class)
public class myServiceImplTest {

    @org.easymock.Mock
    private MyServiceDao myServiceDao;

    @TestSubject
    private MyServiceImpl myServiceImpl = new MyServiceImpl();

    @Test
    public void testGetDatesMi() throws Exception {

        MarketLimits limits = new MarketLimits();
        limits.greaterThenOne(true);
        expect(myServiceDao.getDates()).andReturn(limits);
        replay(myServiceDao);

        myServiceImpl.getDatesMi(12);

    }
}

更新 1

出于某种原因,正在创建 EasyMock 实例 myServiceDao,但是当在 EasyMock 实例上调用方法时,它将 return NULL。我对此的解决方案是在 myServiceImpl 上创建一个 setter 方法来设置我的 myServiceDao 模拟。这是 Deendayal Garg

的建议

更新 2

原来我不需要 setter =) 我更改了标题以反映我面临的实际问题。

由于您正在测试 MyServiceImpl,您可以完全模拟 myServiceDaoMyServiceImpl class 中的 myServiceDao 需要 setter。这是 Mockito spefici,但同样可以在 EasyMock 中完成。

内部测试class你可以做如下的事情。

@Test
public void testGetDatesMi() throws Exception {
    myServiceImpl.setMyServiceDao(myServiceDao);// this is mock
    when(myServiceDao.getDates(anyLong()).thenReturn(mockMarketLimits);

   // call you method here

   // verify
}

好的。为了给出更完整的答案,我尝试了您的代码。 类 之间有很多不一致之处。我尽我所能修复它们,这是一个工作示例。正如您将看到的,注入 Dao 不需要 setter。

@RunWith(EasyMockRunner.class)
public class MyServiceImplTest {

    @org.easymock.Mock
    private MyServiceDao myServiceDao;

    @TestSubject
    private MyServiceImpl myServiceImpl = new MyServiceImpl();

    @Test
    public void testGetDatesMi() throws Exception {

        MarketLimits limits = new MarketLimits();
        limits.greaterThenOne(true);
        expect(myServiceDao.getDates(23)).andReturn(limits);
        replay(myServiceDao);

        myServiceImpl.getDatesMi();

        verify(myServiceDao);
    }
}

public class MarketLimits {
    private boolean b;

    public void greaterThenOne(boolean b) {
        this.b = b;
    }

    public boolean greaterThenOne() {
        return b;
    }
}

public interface MyServiceDao {
    MarketLimits getDates(long orgId);
}

public class MyServiceImpl {

    private MyServiceDao myServiceDao;


    public String getDatesMi() throws Exception {
        MarketLimits subDates = getDates(23);

        System.out.print(subDates);  // this prints out null

        if(subDates.greaterThenOne()){
            // do some things
        }

        return "result";
    }

    public MarketLimits getDates(long orgId) {
        return myServiceDao.getDates(orgId);
    }

    public void setMyServiceDao(MyServiceDao myServiceDao){
        this.myServiceDao = myServiceDao;
    }

}