【问题标题】:parameterized test constructor of junit java error message: Test class should have exactly one public zero-argument constructorjunit java错误消息的参数化测试构造函数:测试类应该有一个公共零参数构造函数
【发布时间】:2020-07-13 17:42:22
【问题描述】:

对于我正在尝试创建的这个参数化测试用例,我真的可以使用一些帮助。无论我创建哪种构造函数,IDE 都会给出错误消息。 这是我的代码:

@RunWith(Parameterized.class)
public class SolverTest {
    final static File folder = new File("C:\\Users\\Azizam\\IdeaProjects\\EightPuzzle\\src\\ModifiedTests");
    final static String destFolder = "C:\\Users\\Azizam\\IdeaProjects\\EightPuzzle\\src\\testresults";
    final static ArrayList<Object[][]> filesList = new ArrayList<>();
    final Object currentBoard = new Object();

    @Parameterized.Parameters
    public static Iterable<Object[][]> data() {
        String path = "";
        int counter = 0;
        for (final File fileEntry : folder.listFiles()) {
            //System.out.println("processing file: " + fileEntry.getName())
            counter++;
            if (counter == 20) break;
            path = destFolder + fileEntry;
            In in = new In(fileEntry.getAbsolutePath());
            int n = in.readInt();
            int moves = in.readInt();
            int[][] tiles = new int[n][n];
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    tiles[i][j] = in.readInt();
            Board b = new Board(tiles);
            Object[][] fileList = new Object[][]{{b, moves}};
            filesList.add(fileList);
        }
        return filesList;
    }

    @Parameterized.Parameter(0)
    private Board board;
    @Parameterized.Parameter(1)
    private int expectedNumberOfMoves;

    public SolverTest(Board board, int expectedNumberOfMoves) {
        this.board = board;
        this.expectedNumberOfMoves = expectedNumberOfMoves;
    }


    @Test
    public void test() {
        assertEquals(expectedNumberOfMoves, new Solver(board).moves());
    }

}

我尝试了不同的方法来创建 1 参数、2 和无参数构造函数。但我从未见过这类问题或解决方案可能是什么。我正在关注this 链接和this 教程。这是我的第一个参数化测试,调试似乎也没有为我提供太多帮助。 我还看到了these 链接,但它们没有帮助。我也可以在 GitHub 或 gist 上为项目的其余部分提供代码。我确实通过正确创建 fileList 来调试我的代码,但我对之后会发生什么或需要发生什么知之甚少。以下是错误的摘录:

java.lang.Exception: Test class should have exactly one public zero-argument constructor

    at org.junit.runners.BlockJUnit4ClassRunner.validateZeroArgConstructor(BlockJUnit4ClassRunner.java:171)
    at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.validateConstructor(BlockJUnit4ClassRunnerWithParameters.java:90)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:127)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:416)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:84)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
    at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.<init>(BlockJUnit4ClassRunnerWithParameters.java:27)
    at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParametersFactory.createRunnerForTestWithParameters(BlockJUnit4ClassRunnerWithParametersFactory.java:16)
    at org.junit.runners.Parameterized.createRunnersForParameters(Parameterized.java:313)
    at org.junit.runners.Parameterized.<init>(Parameterized.java:248)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
    at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder.buildRunner(DefensiveAllDefaultPossibilitiesBuilder.java:113)

这是我的代码的最新版本:

package assignments;

import edu.princeton.cs.algs4.In;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.util.ArrayList;

import static junit.framework.TestCase.assertEquals;

@RunWith(Parameterized.class)
public class SolverTest {
    final static File folder = new File("C:\\Users\\Azizam\\IdeaProjects\\EightPuzzle\\src\\ModifiedTests");
    final static String destFolder = "C:\\Users\\Azizam\\IdeaProjects\\EightPuzzle\\src\\testresults";
    final static ArrayList<Object[][]> filesList = new ArrayList<>();
    final Object currentBoard = new Object();

    @Parameterized.Parameters
    public static Iterable<Object[][]> data() {
        String path = "";
        int counter = 0;
        for (final File fileEntry : folder.listFiles()) {
            //System.out.println("processing file: " + fileEntry.getName())
            counter++;
            if (counter == 20) break;
            path = destFolder + fileEntry;
            In in = new In(fileEntry.getAbsolutePath());
            int n = in.readInt();
            int moves = in.readInt();
            int[][] tiles = new int[n][n];
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    tiles[i][j] = in.readInt();
            Board b = new Board(tiles);
            Object[][] fileList = new Object[][]{{b, moves}};
            filesList.add(fileList);
        }
        return filesList;
    }

    @Parameterized.Parameter(0)
    public Board board;
    @Parameterized.Parameter(1)
    public int expectedNumberOfMoves;

    public SolverTest() {
    }


    @Test
    public void test() {
        assertEquals(expectedNumberOfMoves, new Solver(board).moves());
    }

}

这是调试会话的图片,显示了文件列表中我想要的所有内容。一些板对象如何不转移到我的 Solver 构造函数。

【问题讨论】:

    标签: java unit-testing intellij-idea junit parameterized-unit-test


    【解决方案1】:

    这里是无参数构造函数错误的意思。

    测试类中的构造函数如下:

    public SolverTest(Board board, int expectedNumberOfMoves) {
        this.board = board;
        this.expectedNumberOfMoves = expectedNumberOfMoves;
    }
    

    这需要 2 个参数,因此不是无参数构造函数。下面是一个无参数的构造函数:

    public SolverTest() {
    }
    

    删除2-arg构造函数会起作用,因此不需要显式列出,因为java编译器会自动添加默认的no-arg构造函数。

    但是错误的原因是 Parameterized 测试类的两种方法的混合。

    要么使用带有@Parameterized.Parameters 字段的无参数构造函数(顺便说一下,这些字段必须是公共的而不是私有的),或者删除这些字段并使用带有参数的构造函数。

    这是修改为使用第一种方法的代码(即使用@Parameterized.Parameters 字段):

    @RunWith(Parameterized.class)
    public class SolverTest {
        final static File folder = new File("C:\\Users\\Azizam\\IdeaProjects\\EightPuzzle\\src\\ModifiedTests");
        final static String destFolder = "C:\\Users\\Azizam\\IdeaProjects\\EightPuzzle\\src\\testresults";
        final static ArrayList<Object[][]> filesList = new ArrayList<>();
        final Object currentBoard = new Object();
    
        @Parameterized.Parameters
        public static Iterable<Object[][]> data() {
            String path = "";
            int counter = 0;
            for (final File fileEntry : folder.listFiles()) {
                //System.out.println("processing file: " + fileEntry.getName())
                counter++;
                if (counter == 20) break;
                path = destFolder + fileEntry;
                In in = new In(fileEntry.getAbsolutePath());
                int n = in.readInt();
                int moves = in.readInt();
                int[][] tiles = new int[n][n];
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                        tiles[i][j] = in.readInt();
                Board b = new Board(tiles);
                Object[][] fileList = new Object[][]{{b, moves}};
                filesList.add(fileList);
            }
            return filesList;
        }
    
        @Parameterized.Parameter(0)
        public Board board;
        @Parameterized.Parameter(1)
        public int expectedNumberOfMoves;
    
        public SolverTest() {
        }
    
    
        @Test
        public void test() {
            assertEquals(expectedNumberOfMoves, new Solver(board).moves());
        }
    
    }
    

    【讨论】:

    • 啊好的。我不知道我需要使用一种或另一种方式。在文档或教程中没有看到。让我试一试。
    • @Saaman 我明白了;在重新格式化并更仔细地阅读整个内容之后,我发现异常不是核心问题。我的答案已更新以解决这个问题。
    • 是的,可能不清楚那里有 2 种竞争方法。使用基于字段的方法时会引发“no-arg”构造函数错误,因为 Parameterized 类不希望将参数传递给构造函数。
    • 顺便说一句,为了更容易阅读和管理测试,我使用 cucumber - 你可能想看看它。
    • @Ash-刚试了代码。它给了我一个“没有可运行的方法”的错误。看起来我正在以不转移到单元测试的方式构建文件列表。错误发生在我的 Solver 类中,我检查以确保 Board 不为空
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    相关资源
    最近更新 更多