2014-02-06 103 views
1

我已经开始了一个名为omniprop的开源Scala项目。我目前正在探索的功能是如何让项目的用户堆叠JVM样式的属性提供程序。例如,您可能希望在java.lang.System,Lift的util.Prop和Typesafe的配置库中查找属性。由于omniprop的一些其他约束/特性,我需要这个堆栈配置驻留在一个已知对象中,所以库的其他部分可以从这个堆栈中检索属性。Scala库初始化设计

为了使omniprop正常工作,需要在访问任何属性之前由库的用户调用此配置。因此,任何使用我的库的项目都需要一个可以设置提供者堆栈的引导程序/初始化程序。此初始配置代码的示例如下所示:

import com.joescii.omniprop.providers._ 
PropertyProviders.configure(List(
    SystemPropertyProvider, 
    LiftPropsProvider 
)) 

我面临的挑战是特别针对测试。为了让使用omniprop的项目的测试代码正常工作,必须以某种方式在运行任何测试之前运行上述代码。目前,我没有看到用sbt或我熟悉的任何测试库(如scalatest,scalacheck或specs2)来执行此操作的干净方法。实际上,每个测试套件都需要调用上面的代码片段,这当然不是理想的。

这个问题的另一种方法是Lift所做的,其中每个项目必须有一个名为bootstrap.liftweb.Boot的类,库被调用来设置一切。我发现这是一个合理的方法来处理像Lift这样的Web框架,但对于一个小小的属性帮助程序库似乎太多了。

我真的在这里有两个问题:

  1. 我怎么能有SBT调用上面的设置代码与正确的类加载器的所有测试运行之前?
  2. 更重要的是,这是需要初始化的库的最佳设计,还是有更好的方法?
+0

我会去用的各种“类型安全的建设者”的模式之一。 –

回答

2

使用ScalaTest,当我不得不做类似的事情,我创建了扩展BeforeAndAfterAll一个特点,我混合到每一个需要它的套房。

trait Configure extends Suite with BeforeAndAfterAll { 
    override def beforeAll() { PropertyProviders.configure(/*...*/); } 
    override def afterAll() { PropertyProviders.configure(/*...*/); } 
} 

你只混合它像任何其他特质

trait FooSpec extends Spec with Configure { 
    // ... 
} 
+0

此功能完全是为了作者的目的。 – dmitry

1

您可以将初始化代码放入特质构造函数中,并让您的测试从该特性中扩展。

另一种方法是将该配置作为默认配置,如果未设置配置,则在第一次调用库代码时使用该配置。这将涵盖测试和非测试场景。

混合的方法是让你的sbt测试配置设置一个系统属性。如果设置了该系统属性并且没有设置配置,则将在第一次调用库代码时使用测试配置。