Java类:Calculate.java
public class Calculate { public int sum(int var1, int var2) { System.out.println("Adding values " + var1 + " + " + var2); return var1 + var2; } public int subtract(int var1,int var2){ System.out.println("Subtract values "+ var1+" - "+ var2); return var1-var2; } }
测试类:ParameterizedCalculateTest.java
@RunWith(Parameterized.class) public class ParameterizedCalculateTest { private int expected; private int var1; private int var2; public ParameterizedCalculateTest(int expected, int var1, int var2) { this.expected = expected; this.var1 = var1; this.var2 = var2; } @Parameters public static Collection prepareParamters() { return Arrays.asList(new Integer[][] { { 3, 1, 2 }, { 5, 2, 3 }, { 7, 3, 4 }, { 9, 4, 5 } }); } @Test public void testSum() { System.out.println("Additions with parameters,first:" + var1 + " and second:" + var2); Calculate cal = new Calculate(); Assert.assertEquals(expected, cal.sum(var1, var2)); } }
错误堆栈如下:
java.lang.Exception: No tests found matching Method testSum(com.milan.gjunit.ParameterizedCalculateTest) from org.junit.internal.requests.ClassRequest@739495b8 at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:40) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.(JUnit4TestReference.java:33) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestMethodReference. (JUnit4TestMethodReference.java:25) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:54) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
刚开始看到异常信息:"java.lang.Exception: No tests found matching Method testSum",猜测难道测试类的方法名要和对应java类中的方法名一样么?试下呗,于是将测试类改为:
@RunWith(Parameterized.class) public class ParameterizedCalculateTest { private int expected; private int var1; private int var2; public ParameterizedCalculateTest(int expected, int var1, int var2) { this.expected = expected; this.var1 = var1; this.var2 = var2; } @Parameters public static Collection prepareParamters() { return Arrays.asList(new Integer[][] { { 3, 1, 2 }, { 5, 2, 3 }, { 7, 3, 4 }, { 9, 4, 5 } }); } @Test public void sum() { System.out.println("Additions with parameters,first:" + var1 + " and second:" + var2); Calculate cal = new Calculate(); Assert.assertEquals(expected, cal.sum(var1, var2)); } }
结果还是不行。。。
果断搜索之,搜到stackoverflow上有类似的问题: http://stackoverflow.com/questions/12798079/initializationerror-with-eclipse-and-junit4-when-executing-a-single-test/18438718#18438718。
于是乎抱着试试看的想法,扩展Parameterized.Java如下:
public class IDECompatibleParameterized extends Parameterized { public IDECompatibleParameterized(Class> klass) throws Throwable { super(klass); } public void filter(Filter filter) throws NoTestsRemainException { super.filter(new FilterDecorator(filter)); } /** * Running single test in case of parameterized test causes issue as explained in * http://youtrack.jetbrains.com/issue/IDEA-65966 * * As a workaround we wrap the original filter and then pass it a wrapped description * which removes the parameter part (See deparametrizedName) */ private static class FilterDecorator extends Filter { private final Filter delegate; private FilterDecorator(Filter delegate) { this.delegate = delegate; } @Override public boolean shouldRun(Description description) { return delegate.shouldRun(wrap(description)); } @Override public String describe() { return delegate.describe(); } } private static Description wrap(Description description) { String name = description.getDisplayName(); String fixedName = deparametrizedName(name); Description clonedDescription = Description.createSuiteDescription(fixedName,description.getAnnotations().toArray(new Annotation[0])); for(Description child : description.getChildren()){ clonedDescription.addChild(wrap(child)); } return clonedDescription; } private static String deparametrizedName(String name) { //Each parameter is named as [0], [1] etc if(name.startsWith("[")){ return name; } //Convert methodName[index](className) to //methodName(className) int indexOfOpenBracket = name.indexOf('['); int indexOfCloseBracket = name.indexOf(']')+1; return name.substring(0,indexOfOpenBracket).concat(name.substring(indexOfCloseBracket)); } }
PS:装饰器模式用的很赞。。。
然后再把测试类改为:
@RunWith(IDECompatibleParameterized.class) public class ParameterizedCalculateTest { private int expected; private int var1; private int var2; public ParameterizedCalculateTest(int expected, int var1, int var2) { this.expected = expected; this.var1 = var1; this.var2 = var2; } @Parameters public static Collection prepareParamters() { return Arrays.asList(new Integer[][] { { 3, 1, 2 }, { 5, 2, 3 }, { 7, 3, 4 }, { 9, 4, 5 } }); } @Test public void sum() { System.out.println("Additions with parameters,first:" + var1 + " and second:" + var2); Calculate cal = new Calculate(); Assert.assertEquals(expected, cal.sum(var1, var2)); } }
修改点为: @RunWith(IDECompatibleParameterized.class)
果断Pass。
记录下,顺便对国际友人表示感谢,希望对遇到类似问题的朋友有所帮助。