代码之家  ›  专栏  ›  技术社区  ›  thequark

ScalaTest:单例对象重新初始化问题

  •  9
  • thequark  · 技术社区  · 16 年前

    class Parser{...}
    object Resolver {...}
    

    我写的测试用例有点像这样

       describe("Syntax:") {
        val dir = new File("tests\\syntax");
        val files = dir.listFiles.filter(
                        f => """.*\.chalice$""".r.findFirstIn(f.getName).isDefined);
    
        for(inputFile <- files) {
          val parser = new Parser();
          val c = Resolver.getClass.getConstructor();
          c.setAccessible(true);
          c.newInstance();
    
          val iserror = errortest(inputFile)
          val result = invokeparser(parser,inputFile.getAbsolutePath) //local method
          it(inputFile.getName + (if (iserror)" ERR" else " NOERR") ){
          if (!iserror) result should be (ResolverSuccess()) 
            else if(result.isInstanceOf[ResolverError]) assert(true)
          }
        }
      }
    

    更新 :根据Daniel的建议,我更新了代码,还添加了更多细节。

    更新

    最终更新 :问题是与解析程序以外的单例对象有关,它位于其他文件中,因此我不知怎的错过了它。我用丹尼尔·斯皮瓦克的回答解决了这个问题。这是一种肮脏的方式,但它也是唯一的事情,考虑到我的情况,也考虑到我正在编写一个测试代码,这是不会投入生产使用的事实。

    2 回复  |  直到 16 年前
        1
  •  7
  •   Daniel Spiewak    16 年前

    根据语言规范,不,没有办法重新创建单例对象。然而,它 可以反射地调用一个单例的构造函数,它覆盖了内部 MODULE$ 包含实际单例值的字段:

    object Test
    
    Test.hashCode    // => e.g. 779942019
    
    val c = Test.getClass.getConstructor()
    c.setAccessible(true)
    c.newInstance()
    
    Test.hashCode    // => e.g. 1806030550
    

    曾经 做这个。我会非常努力地调整代码,而不是像这样玩鬼鬼祟祟的把戏。然而,如果事情如你所说,你真的没有其他选择,这至少是一些东西。

        2
  •  4
  •   Bill Venners    16 年前

    ScalaTest有几种方法可以让您在测试之间重新初始化。然而,如果不知道更多,这个问题很难回答。主要的问题是,需要什么来重新初始化singleton对象?如果在没有实例化新的单例对象的情况下无法重新初始化单例对象,那么您需要确保每个测试都重新加载了单例对象,这将需要使用自定义类装入器。不过,我觉得很难相信有人会这样设计。你能用这样的细节更新你的问题吗?我稍后再看一看,看看这些额外的细节是否能让答案更明显。

        3
  •  0
  •   סטנלי גרונן Abhishek Singh    6 年前

    没有答案,但我有一个简单的例子,说明您可能需要重置singleton对象,以便在多种潜在情况下测试singleton构造。考虑一些愚蠢的事情,比如下面的代码。您可能需要编写测试来验证在环境设置不正确时是否引发异常,以及编写测试来验证在环境设置不正确时是否未发生异常。我知道,我知道每个人都说,“当环境设置不正确时提供默认值”,但我不想这样做;这将导致问题,因为不会有通知,你正在使用错误的系统。

    object RequiredProperties extends Enumeration {
      type RequiredProperties = String
    
      private def getRequiredEnvProp(propName: String) = {
        sys.env.get(propName) match {
          case None => throw new RuntimeException(s"$propName is required but not found in the environment.")
          case Some(x) => x
        }
      }
    
      val ENVIRONMENT: String = getRequiredEnvProp("ENVIRONMENT")
    }
    

    用法:

    Init(RequiredProperties.ENVIRONMENT)
    

    推荐文章