如何编写Junit for Interface默认方法

时间:2017-01-22 11:00:06

标签: java unit-testing junit java-8

请帮助编写Junit接口默认方法。

public interface ABC<T, D, K, V> {
    default List<String> getSrc(DEF def, XYZ xyz) throws Exception {
    }
}

ABC:接口名称。 DEF和XYZ:类名

5 个答案:

答案 0 :(得分:3)

正如答案中所建议的,为界面创建实现类并对其进行测试,对于我在vmax界面中修改getSrc方法的示例,如下所示:< / p>

ABC

为此创建了一个实现类,可选地,您可以创建另一个调用super方法的方法,并为两者编写import java.util.ArrayList; import java.util.List; public interface ABC<T, D, K, V> { default List<String> getSrc(DEF def, XYZ xyz) { final List<String> defaultList = new ArrayList<>(); defaultList.add("default"); defaultList.add("another-default"); return defaultList; } } ,如下所示:

@Test

实施的对应测试类如下:

import java.util.List;

public class ABCImpl implements ABC<String, Integer, String, Integer> {

    public List<String> getSrcImpl(DEF def, XYZ xyz) {
        final List<String> list = getSrc(def, xyz);
        list.add("implementation");
        return list;
    }
}

答案 1 :(得分:3)

我认为有一种更简单的方法。 它包括使用要在测试类中测试的方法来实现接口,并直接调用默认类型的方法。如有必要,将对内部调用的对象进行模拟。前面的示例如下:

接口)

public interface ABC<T, D, K, V> {
    default List<String> getSrc(DEF def, XYZ xyz) throws Exception {
      list<String>() result=new Arraylist<String>();
      result.add(def.toString());
      result.add(xyz.toString());
      return result;
    }
}

测试类)

...        
@RunWith(MockitoJUnitRunner.class)
public class ABCTest implements ABC{

    @Test
    public void testGetSrc() {

        list<String>() result=getSrc(new DEF("Hi!"),new XYZ("bye!"));

        int actual=result.size();
        int expected=2;
        assertEquals(expected, actual);

    }

如果您需要测试异常的启动,就足以迫使其从错误的参数中释放并正确配置测试:

...        
@Test(expected = GenericRuntimeException.class)
public void test....
...

我已经用类似的代码对其进行了检查,并且可以正常工作。也可以在覆盖率分析中正确收集它。

答案 2 :(得分:1)

您可以创建一个实现您的界面的类,也可以让您的测试实现它。第二个似乎是一个较短的解决方案:

public class FunctionCallingTransactionTemplateTest implements FunctionCallingTransactionTemplate {
    private final Object object = Mockito.mock(Object.class);

    @Test
    public void should_invoke_function() throws Exception {
        // given
        when(object.toString()).thenReturn("salami");

        // when
        String result = functionCallingTransactionTemplate().execute((status) -> object.toString());

        // then
        assertThat(result).isEqualTo("salami");
    }
}

答案 3 :(得分:1)

如果您使用的是Mockito,则对默认方法(又称“防御者”)进行单元测试的最简单方法是使用界面制作spy 1 类literal 2 。然后可以像往常一样在返回的间谍实例上调用默认方法。以下示例演示:

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;

interface OddInterface {
    // does not need any unit tests because there is no default implementation
    boolean doSomethingOdd(int i);

    // this should have unit tests because it has a default implementation
    default boolean isOdd(int i) {
        return i % 2 == 1;
    }
}

public class OddInterfaceTest {
    OddInterface cut = spy(OddInterface.class);

    @Test
    public void two_IS_NOT_odd() {
        assertFalse(cut.isOdd(2));
    }

    @Test
    public void three_IS_odd() {
        assertTrue(cut.isOdd(3));
    }
}

(已通过Java 8和mockito-2.24.5测试)

1 人们经常警告使用spy可以表示代码或测试气味,但是测试默认方法是使用{{1 }}是一个想法。

2 在撰写本文时(2019年),接受类文字的spy的签名被标记为spy,但已经自mockito-1.10.12于2014年发布以来一直存在。此外,support for default methods in Mockitomockito-2.1.0于2016年发布以来一直存在。可以肯定的是,该方法将来会继续有效版本的Mockito。

答案 4 :(得分:0)

答案很简单。无需嘲笑或暗中监视,只需为接口创建一个匿名对象而无需覆盖默认方法即可。

例如:

interface Adder {
  default sum(Integer...n) {
    return Arrays.stream(n).reduce(0, Integer::sum);
  }
} 

// Junit 4
class AdderTest {

  private Adder adder;

  @Before
  public void setup() {}
    adder = new Adder(){}; // not overriding default methods
  }

  @Test
  public void testSum() {
    Assert.assertEquals(3, adder.sum(1, 2));
  }
}