Java Mockit:如何在JMockit中模拟泛型类方法

时间:2016-03-24 09:33:55

标签: java unit-testing generics junit jmockit

您好我有以下课程

public class DataAccessLayer<T> {
  public T getData(Class<?> dataInfoType ,Integer id){
  //Some logic here
  } 
}

public class ServiceLayer{
    //this method has to be tested
     public Integer testingMethode{
         //The following line should be mocked
         UtilClass info =  new DataAccessLayer<UtilClass>().getData(UtilClass.class, 1); 
        retutn info.getSomeFieldWithIntegerValue();
     }
 }

我想为testingMethode编写测试用例,因为我需要在getData()中模拟DataAccessLayer<T>方法

是否可以使用jmockit模拟模板(通用)类?

3 个答案:

答案 0 :(得分:1)

在JMockit中,实际上不需要在ServiceLayer类中创建保持变量,也不需要创建DataLayer的参数化子类。以下测试工作正常:

package com.example.dsohl;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;

import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Mocked;
import mockit.Tested;
import mockit.integration.junit4.JMockit;

@RunWith(JMockit.class)
public class TestTest {

    public static class UtilClass {
        public Integer foo() {
            return 5;
        }
    }

    public static class DataLayer<T> {
        public T getItem(Class<T> clazz, int itemId) {
            return null;
        }
    }

    public static class ServiceLayer {
        public Integer testMethod() {
            UtilClass util = new DataLayer<UtilClass>().getItem(UtilClass.class, 1);
            return util.foo();
        }
    }

// Test really begins here
    @Tested ServiceLayer svc;
    @Mocked DataLayer<UtilClass> data;
    @Mocked UtilClass util;

    @Test
    public void testDateSubtraction() throws Exception {
        new Expectations() {
            {
                new DataLayer<UtilClass>(); result = data;
                onInstance(data).getItem(UtilClass.class, 1); result = util;
                util.foo(); result = 37;
            }
        };

        Integer i = svc.testMethod();
        assertThat(i, equalTo(37));
    }

}

一些注意事项:首先,我的DataLayer.getItem()返回null,因此如果注入失败,我们会得到一个NullPointerException,很好而且很明显。显然你的代码不会像这样工作;这只是为了说服你。

其次,我使用onInstance(),以便我们可以100%确定DataLayer构造函数的结果是我们在测试的后续步骤中使用的结果。 Expectations对象上@Mocked的默认行为是记录对该类的任何对象的期望;这就是我们如何确定它正在使用的我们的对象。 (通常我不会为此烦恼,但在使用new时,我希望确定。)

最后,我省略了在这种情况下我可能会做的其他一些事情,例如使用Verifications块等等。只是尽量做到尽可能简单。

享受!

答案 1 :(得分:1)

泛型类可以像非泛型类一样进行模拟:

     start      end id
#  326.019  340.133  1
#  451.142  469.626  2
#  597.985  617.004  3
#  778.896  797.714  4
# 1014.590 1038.280  5

df = structure(list(start = c(326.019, 451.142, 597.985, 778.896, 
1014.59), end = c(340.133, 469.626, 617.004, 797.714, 1038.28
), id = 1:5), .Names = c("start", "end", "id"), row.names = c(NA, 
-5L), class = "data.frame")

答案 2 :(得分:0)

(我只能真正回答Mockito,因为这是我最熟悉的;但同样的原则应适用于其他模拟框架。)

首先,您需要能够将>>> any((ts - mavg).dropna().abs() > 1e-14) False 注入DataAccessLayer<UtilClass>,例如

ServiceLayer

这会破坏使用class ServiceLayer { private final DataAccessLayer<UtilClass> dal; ServiceLayer(DataAccessLayer<UtilClass> dal) { this.dal = dal; } public Integer testingMethode() { UtilClass info = dal.getData(UtilClass.class, 1); return info.getSomeFieldWithIntegerValue(); } } 创建的DataAccessLayer<UtilClass>的静态耦合。

现在,您可以通过创建非泛型子类来创建new的模拟实例:

DataAccessLayer<UtilClass>

然后创建一个模拟实例:

class UtilClassDataAccessLayer extends DataAccessLayer<UtilClass> {}

现在,您可以根据需要配置此模拟,并将其传递到DataAccessLayer<UtilClass> mocked = mock(UtilClassDataAccessLayer.class);

ServiceLayer