我正在使用ScalaTest测试我在Scala中编写的解析器.解析器一次处理一个文件,它有一个单独的对象,如下所示:
class Parser{...}
object Resolver {...}
Run Code Online (Sandbox Code Playgroud)
我写的测试用例有点像这样
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在每次迭代时,单个对象解析器中先前迭代的副作用都不会被清除.
有没有办法指定scalatest模块重新初始化单例对象?
更新:使用Daniel的建议,我已经更新了代码,还添加了更多细节.
更新:显然是Parser正在做一些可疑的事情.在后续调用中,它不会丢弃先前的AST.奇怪.因为这是一个偏离主题,我会挖掘更多,并可能使用一个单独的线程进行讨论,谢谢大家回答
最后更新:问题在于解析器以外的单个对象,它在其他文件中,所以我不知何故错过了它.我能用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
Run Code Online (Sandbox Code Playgroud)
现在,我已经与您共享了邪恶的秘密,让我提醒你永远,永远做到这一点.我会非常努力地调整代码,而不是像这样玩怪异的技巧.但是,如果事情就像你说的那样,而你真的没有别的选择,那至少就是这样.