我正在测试使用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/