如何使用JMockit模拟MyBatis映射器方法

时间:2015-03-06 02:35:59

标签: jmockit

我们有一个服务组件(@service),它在内部使用MyBatis来进行CRUD操作。所有组件都由Spring管理。

让我们假设我们的MyBatis映射器文件

class MyBatisMapper{

        public void getData(Map<String,Object> arg);
}

在我们的mybatis xml文件中,我们为可调用语句定义了元素。 arg是一个包含IN和OUT参数的地图。

我们的服务组件就像

@Service("myService")
class MyService{

@Autowired
private MyBatisMapper myMapper;

public void processData(){

  Map<String,Object> input = new HashMap<String,Object>();
  ............
  ............
  myMapper.getDat(input);

  Object response =  input.get("RESPONSE");
  //process response and so on
}

我的目标是为服务组件编写Junits,而不必与DB进行交互。所以,我尝试使用JMockIt来模拟一些DAO操作

我的尝试是ike

@Mocked
@Injectable
private MyBatisMapper myMapper;

@Test
    public void testService() {

        new NonStrictExpectations(){
            {
                Map<String,Object> input = new HashMap<String,Object>();
                                 input.put("xxx,"yyy");
                myMapper.getData(input);
            }
        };

    }

但是当我运行我的测试时,我注意到这个调用是通过实际数据库进行的,而不是通过模拟调用。

如何确保只调用模拟的组件,而不是实际的对象

2 个答案:

答案 0 :(得分:0)

@Injectable模拟实例仅被注入@Tested个对象。要从模拟方法指定返回值,您需要将其分配给result字段。因此,测试应如下所示:

@Tested MyService myService;
@Injectable MyBatisMapper myMapper;

@Test
public void testService() {
    final Map<String,Object> data = new HashMap<String, Object>();
    data.put("RESPONSE", "yyy");

    new Expectations() {{
        myMapper.getData((Map<String, Object>) any); result = data;
    }};

    myService.processData();

    // Assert some expected outcome.
}

答案 1 :(得分:0)

谢谢Rogerio。我试图按照你提到的方法,但我仍然看到调用转到实际对象。有一点我之前没有提到过。我的项目是基于弹簧的,组件都是自动装配的。

我的测试有

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/test-applicationContext.xml"})

和test-applicationContext.xml进行组件扫描。所以我认为,Spring正在注入忽略模拟指令的实际对象。

我错了吗?