【问题标题】:How to Mock classes that are being instantiated within the test class with EasyMock?如何使用 EasyMock 模拟在测试类中实例化的类?
【发布时间】:2016-04-21 15:26:36
【问题描述】:

我正在尝试测试一个有点复杂的程序。 getDatesMi 调用同一类中的方法。该方法拨打电话 到返回查询结果的接口方法,该查询结果被强制转换为 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;
}

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

}

待测主类

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 实例上调用方法时,它会返回 NULL。我对此的解决方案是在 myServiceImpl 上创建一个 setter 方法来设置 myServiceDao 模拟。这是来自Deendayal Garg的建议

更新 2

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

【问题讨论】:

  • 我用 null 错误发生的位置更新了问题

标签: java spring unit-testing junit easymock


【解决方案1】:

好的。为了给出更完整的答案,我尝试了您的代码。类之间有很多不一致的地方。我尽我所能修复它们,这是一个工作示例。如您所见,注入 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;
    }

}

【讨论】:

  • 感谢您的建议,但是调用验证返回此错误 java.lang.IllegalStateException: 在 org.easymock.internal.MocksControl.verify(MocksControl.java:223) 的记录状态中不允许调用验证org.easymock.EasyMock.verify(EasyMock.java:2007)
  • Arg... 抱歉。应该是replay
  • 谢谢,太好了。
【解决方案2】:

由于您正在测试MyServiceImpl,您可以完全模拟myServiceDao。您需要在MyServiceImpl 类中为myServiceDao 设置一个setter。这是 Mockito spefici,但也可以在 EasyMock 中完成。

在测试类中,您可以执行以下操作。

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

   // call you method here

   // verify
}

【讨论】:

  • 这是模拟语法。而且你不需要设置模拟。它将由跑步者自动完成
  • 是的。但是也不需要调用setter
猜你喜欢
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多