当前位置: 首页 > 知识库问答 >
问题:

通过枚举对Singleton进行单元测试将抛出java.lang.NoClassDefoundError

危卜鹰
2023-03-14

这很奇怪,我不知道该如何解释清楚。请耐心听我说,请查看代码片段以了解详细信息。

我使用枚举实现了一个单例。枚举有一个私有构造函数,在构造对象之前,我只在其中执行很少的操作和验证。对于所有这些验证,我将抛出一些异常(如IllegalArgumentException)。

我的测试用例包括针对负面和正面场景的测试。每当有两个以上的测试用例混合了负面和正面的测试用例时,我就会得到以下异常:java.lang.NoClassDefoundError:Could not initialize class com.blah.blah.singletonClass。请检查下面的完整代码。我正在使用以下技术堆栈:

JDK 1.7_51
Spring 4.0.0.RELEASE
testng 6.8.7
public enum SingletonUsingEnum {
  INSTANCE;

  // Logger
  private final Logger logger = LoggerFactory.getLogger(SingletonUsingEnum.class);

  private SingletonUsingEnum() {
    final MyConfig myConfig = MyConfigManager.getMyConfig();
    if(myConfig == null) {
      throw new IllegalArgumentException("MyConfig is null");
    }

    if(StringUtils.isBlank(myConfig.getConfigValue())) {
      throw new IllegalArgumentException("myConfig.configValue value null/empty");
    }

    if(StringUtils.isBlank(myConfig.getOtherConfigValue())) {
      throw new IllegalArgumentException("myConfig.otherConfigValue null/empty");
    }

    logger.info("This is a singleton using enum");
  } 
}

MyConfig.java

public class MyConfig {
  private String configValue;
  private String otherConfigValue;

  public MyConfig(final String configValue, final String otherConfigValue) {
    this.configValue = configValue;
    this.otherConfigValue = otherConfigValue;
  }

  public String getConfigValue() {
    return configValue;
  }

  public String getOtherConfigValue() {
    return otherConfigValue;
  } 
}

MyConfigManager.java

public class MyConfigManager {
  private final static ConcurrentMap myConfigHolder = new ConcurrentHashMap();

  public static void registerMyConfig(final MyConfig myConfig) {
    myConfigHolder.put("myConfig", myConfig);
  }

  public static MyConfig getMyConfig() {
    return myConfigHolder.get("myConfig");
  }

  public static void clearAll() {
    myConfigHolder.clear();
  }
}

SingletonusingEnumTest.java

@ContextConfiguration(classes = {SingletonUsingEnumTest.SpringConfig.class})
public class SingletonUsingEnumTest extends AbstractTestNGSpringContextTests {
  // Logger
  private static final Logger logger = LoggerFactory.getLogger(SingletonUsingEnumTest.class);

  @AfterMethod
  public void cleanUp() {
    MyConfigManager.clearAll();
  }

  @Test(expectedExceptions = {IllegalArgumentException.class, ExceptionInInitializerError.class})
  public void nullMyConfig() {
    MyConfigManager.registerMyConfig(new MyConfig("", ""));
    final SingletonUsingEnum singleton = SingletonUsingEnum.INSTANCE;
  }

  @Test
  public void validMyConfig_nullConfigValue() {
    MyConfigManager.registerMyConfig(new MyConfig("", "b"));
    final SingletonUsingEnum singleton = SingletonUsingEnum.INSTANCE;
  }

  @Test(dependsOnMethods = {"nullMyConfig"})
  public void allValidData() {
    MyConfigManager.registerMyConfig(new MyConfig("a", "b"));
    final SingletonUsingEnum singleton = SingletonUsingEnum.INSTANCE;
  }

  @Configuration
  @EnableAspectJAutoProxy(proxyTargetClass = true)
  public static class SpringConfig {

  }
}
[TestNG] Running:
  /private/var/folders/l6/hmmqvjpj13ggmyc69sk1s5740000gn/T/testng-eclipse-135911498/testng-customsuite.xml

PASSED: nullMyConfig
FAILED: validMyConfig_nullConfigValue
java.lang.NoClassDefFoundError: Could not initialize class com.demo.singleton.SingletonUsingEnum
    at com.demo.singleton.SingletonUsingEnumTest.validMyConfig_nullConfigValue(SingletonUsingEnumTest.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:200)
    at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:157)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:212)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:707)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)

FAILED: allValidData
java.lang.NoClassDefFoundError: Could not initialize class com.demo.singleton.SingletonUsingEnum
    at com.demo.singleton.SingletonUsingEnumTest.allValidData(SingletonUsingEnumTest.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:200)
    at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:157)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:212)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:707)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)


===============================================
    Default test
    Tests run: 3, Failures: 2, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 3, Failures: 2, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@6997f7f4: 8 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@4474c7fe: 14 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 6 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@395e7bc4: 14 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@71419cf7: 5 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@6015eb5a: 31 ms

共有1个答案

费锋
2023-03-14

您的测试尝试使用您的单例。因此JVM加载并初始化枚举。作为此过程的一部分,它调用您的构造函数来初始化唯一枚举实例。构造函数引发异常,从而阻止正确加载类。

一旦JVM尝试加载类但失败了,它就不会再尝试加载它了。

单例是一种反模式。在一个类加载时急切地初始化的单例中进行这种导致异常的过程是一个非常糟糕的主意。

 类似资料:
  • 问题内容: 我已经看过Scala有关模拟Javaenum和case类与Enumeration的问题,但是似乎付出了太多的努力却却获得了太多的好处。 基本上,我希望有一个方法可以返回的所有单例对象,而无需重复几次。 这是我的代码的样子: 该方法应该返回类似如下的内容: 一切都应该发生在特征中,所以我只需要扩展它即可获得功能。 有什么建议可以做到这一点吗?这个想法是访问类并找到它们正在扩展的类的所有单

  • 问题内容: 如何在单元测试中测试 hashCode()函数? 问题答案: 每当我覆盖equals和hash代码时,我都会按照Joshua Bloch在“ Effective Java”第3章中的建议编写单元测试。我确保equals和hash代码是自反的,对称的和可传递的。我还确保“不等于”对所有数据成员均正常工作。 当我检查对equals的调用时,我还要确保hashCode的行为符合预期。像这样:

  • 枚举具有名为'hash value'的属性,该属性是枚举内的索引。

  • 问题内容: 我试图使用sprint-test和模仿对象编写Servlet的单元测试 我的Maven依赖是: org.springframework spring-test 4.0.3.RELEASE 问题答案: 我需要使用javax.selvlet-api替换javaee-api的依赖项,如下所示:

  • 问题内容: 我一直在学习AngularJS,并且在单元测试方面进展非常顺利,但是我遇到了一个棘手的问题。 假设我有一个简单的表格,例如: 如果我正在测试类似控制器的东西,我知道我会这样写(使用Jasmine + Karma): 但是我不知道我需要注入哪些服务,也没有运气在指南或文档中找到有关单元测试的文档。 一个单元如何在Angular中测试表单? 问题答案: 我不认为这是对此类内容进行单元测试的

  • 本文向大家介绍对Angular.js Controller如何进行单元测试,包括了对Angular.js Controller如何进行单元测试的使用技巧和注意事项,需要的朋友参考一下 一、写个简单的Angular App 在开始写测试之前,我们先写一个简单的计算App,它会计算两个数字之和。 代码如下: 二、简单说说里面涉及的一些基本概念: 创建一个 module 什么是angular.modul