我正在测试使用ScalaTest在Scala中编写的解析器。解析器一次处理一个文件,它具有一个单例对象,如下所示:

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)
      }
    }
  }

现在,在每次迭代中,单例对象解析器内部以前的迭代的副作用都没有清除。

有什么方法可以指定scalatest模块来重新初始化单例对象?

更新:使用Daniel的建议,我更新了代码,还添加了更多详细信息。

更新:显然是解析器正在执行某些操作。在随后的调用中,它不会丢弃先前的AST。奇怪的。由于这不是主题,因此我将继续进行探讨,并可能使用单独的主题进行讨论,谢谢大家的回答。

最终更新:问题出在Resolver之外的单例对象上,它在其他文件中,所以我以某种方式错过了它。我能够使用Daniel Spiewak的回复来解决此问题。考虑到我的情况并且考虑到我正在编写测试代码的事实,这是做事情的肮脏方式,但也是唯一的事情,这不会用于生产。

最佳答案

根据语言规范,没有,没有办法重新创建单例对象。但是,可以以反射方式调用单例的构造函数,该构造函数将覆盖内部MODULE$字段,该字段包含实际的单例值:

object Test

Test.hashCode    // => e.g. 779942019

val c = Test.getClass.getConstructor()
c.setAccessible(true)
c.newInstance()

Test.hashCode    // => e.g. 1806030550

现在,我已经与您分享了这个邪恶的 secret ,让我永远不要警告您这样做。我会非常努力地调整代码,而不是像这样玩花招。但是,如果事情如您所说,并且您确实没有其他选择,那么至少是这样。

关于ScalaTest:单例对象重新初始化的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3410103/

10-16 03:49