【问题标题】:Test class should have exactly one public zero-argument constructor测试类应该只有一个公共的零参数构造函数
【发布时间】:2022-02-08 03:40:24
【问题描述】:

我写了一个测试类,如下所示

public class MyParameterizedClassTest extends BaseRepositoryTest {
    private int multiplierA;
    private int multiplierB;
    public MyParameterizedClassTest(int multiplierA) {
        this.multiplierA = multiplierA;

    }   

    @Parameters
    public static Collection<Object[]> data() { 
        Object[][] data = new Object[][] { { 1 }, { 5 }, { 121 } };
        return Arrays.asList(data);
    }

    @Test
    public void testMultiplyException() {
        assertEquals("Result", multiplierA * multiplierA,multiply(multiplierA));
    }

    public int multiply(int a){
        return a*a;
    }
 }

我的 BaseRepositoryTest 课程如下

@RunWith (Parameterized.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public abstract class BaseRepositoryTest extends
    AbstractJUnit4SpringContextTests {



    @Inject
    SessionFactory sessionFactory;

    private Transaction transaction;

    public Session getSession() {
        Session session;
        try {
            session = sessionFactory.getCurrentSession();
        } catch (SessionException se) {
            session = sessionFactory.openSession();
        }
        return session;
    }

    @Before
    public void setUp() throws Exception {
        transaction = getSession().beginTransaction();
    }

    @After
    public void tearDown() throws Exception {
        if (transaction != null) {
            transaction.rollback();
        }
        getSession().close();
    }

    @Before
    public void baseSetUp() {
        MockitoAnnotations.initMocks(this);
    }
}

当我运行我的测试类时,它会显示,

 Test class should have exactly one public zero-argument constructor:at 
 org.junit.runners.BlockJUnit4ClassRunner.validateZeroArgConstructor

我想用@parameters做一个测试方法,所以请谁能帮忙找到解决办法

【问题讨论】:

  • 看起来错误的测试运行器正在执行您的任务。我们需要弄清楚为什么要解决这个问题。
  • 你确定你的类都被正确编译了吗?您的例外提到了BlockJUnit4ClassRunner,但Parameterized 不是BlockJUnit4ClassRunner 的子类。见junit.sourceforge.net/javadoc/org/junit/runners/…。似乎您编译的代码不包含@RunWith (Parameterized. class)
  • 是的,我尝试使用 @RunWith (Parameterized.class),现在它在 com.kgfsl.collections.core.security.BaseRepositoryTest.getSession(BaseRepositoryTest.java:45) 处显示 java.lang.NullPointerException com.kgfsl.collections.core.security.BaseRepositoryTest.setUp(BaseRepositoryTest.java:54) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  • @Duncan:我的回答肯定是基于基本的 Java 知识:Java Constructors-Note,请参阅注释。如果一个类定义了一个显式构造函数,它就不再有一个默认构造函数来设置对象的状态。如果这样的类需要默认构造函数,则必须提供其实现。如果在这种情况下未提供显式默认构造函数,则任何调用默认构造函数的尝试都将是编译时错误。
  • @RenéLink 它非常适合我 rene。感谢您的解决方案

标签: java junit parameters


【解决方案1】:

JUnit 4 与 5(木星)

我在导入错误的Test 类时遇到了这个问题。当构造函数使用 JUnit 5 功能时,我导入了旧的 org.junit.Test 而不是 org.junit.jupiter.api.Test。

【讨论】:

    【解决方案2】:

    我认为问题在于您定义了两个测试运行器。一个是你自己的@RunWith (Parameterized. class) 一个是spring 自带的,因为AbstractJUnit4SpringContextTests 定义了一个@RunWith(SpringJUnit4ClassRunner.class)。

    由于Junit 只能处理一个@RunWith,所以只能使用@Parameterized 或AbstractJUnit4SpringContextTests。如果你想同时使用这两者,你必须使用 @Parameterized,而不是使用 SpringJUnit4ClassRunner 自己执行的相同逻辑。

    一个简单的方法是只使用spring的org.springframework.test.context.TestContextManager。

    @RunWith(Parameterized.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public abstract class BaseRepositoryTest extends AbstractJUnit4SpringContextTests {
    
        private TestContextManager testContextManager;
    
        @Before
        public void setUpContext() throws Exception {
            this.testContextManager = new TestContextManager(getClass());
            this.testContextManager.prepareTestInstance(this);
        }
    
    }
    

    但这只能确保调用TestExecutionListeners。 Spring 通常更像是应用程序上下文缓存等。还应实现关闭应用程序上下文的拆卸方法。

    【讨论】:

    • 在规则中会更好
    • @AlexisHassler 是的。 Rule 的问题是您无法轻松获取测试实例,而 testContextManager.prepareTestInstance(this); 需要它
    • 是的,我尝试了这段代码,但在 com.kgfsl.collections.core.security.BaseRepositoryTest.getSession(BaseRepository‌​Test.java:45) 在 com.kgfsl 出现类似 java.lang.NullPointerException 的错误.collections.core.security.BaseRepositoryTest.setUp(BaseRepositoryTest.‌​java:54) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    • @MdAslam 你试过@Autowired而不是@Inject吗?
    【解决方案3】:

    如果您正在运行单个测试,请确保您正确编写了测试类名称

    我犯的一个常见错误是有一个名为 'Foo' 的类和一个名为

    的测试类

    'FooTest'

    并使用

    运行单个单元测试

    'Foo'

    而不是“FooTest”

    如果 'Foo' 有一个带参数的公共构造函数,我会收到错误:

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

    【讨论】:

    • 是的!这是我!谢谢。需要将Test 添加到我的测试调用命令的末尾。
    【解决方案4】:

    当您的类未定义为公共时会引发此错误 在你的情况下它是抽象的,所以它不能被实例化来测试propouses

    【讨论】:

      【解决方案5】:

      尝试从 MyParameterizedClassTest 类中删除构造函数。

      当我的测试类有一个公共构造函数时,我收到了这个错误。删除后,它开始工作了。

      【讨论】:

        【解决方案6】:

        我有一个答案,它可以在我的机器上修复 JUnit4 -> 当你检查异常时

         org.junit.runners.BlockJUnit4ClassRunner.validateZeroArgConstructor(BlockJUnit4ClassRunner.java:171)
         org.junit.runners.BlockJUnit4ClassRunner.validateConstructor(BlockJUnit4ClassRunner.java:148)
        

        进入第一个异常

        protected void validateZeroArgConstructor(List<Throwable> errors) {
            if(!this.getTestClass().isANonStaticInnerClass() && this.hasOneConstructor() && this.getTestClass().getOnlyConstructor().getParameterTypes().length != 0) {
                String gripe = "Test class should have exactly one public zero-argument constructor";
                errors.add(new Exception(gripe));
            }
        
        }
        

        它会检查你的构造函数是否无参数 试试setter注入或者field(->官方不推荐field)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多