2011-07-03 90 views
2

我想重寫ScalaTest特徵BeforeAndAfterEach來爲所有測試實現一次這些東西。最後我把它編譯出來,但我不明白爲什麼。覆蓋特徵和自我類型

trait MySetup extends BeforeAndAfterEach { 
    this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite => 
    var service: String = _ 

    abstract override def beforeEach(): Unit = { 
    service = "apa" 
    super.beforeEach() 
    } 

    abstract override def afterEach(): Unit = { 
    service = "" 
    } 
} 

是得到它的工作的事情是行:

this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite => 

我發現它在BeforeAndAfterEach開始執行並複製它。

它做什麼,爲什麼我需要它?

更新:

這是一個更簡單的版本。

trait MySetup extends FlatSpec with BeforeAndAfterEach { 
    var service: String = _ 

    override def beforeEach { 
    service = "apa" 
    super.beforeEach 
    } 

    override def afterEach { 
    service = "" 
    super.afterEach 
    } 
} 

回答

5

BeforeAndAfterEach具有自型套件,這意味着BeforeAndAfterEach只能在混合以延伸套件類型。 ScalaTest希望您先選擇主要套件類型,然後再進行混合行爲。

自我類型聲明不是繼承子屬性,所以你必須重新聲明自我類型。

以下問題有自我的類型和子性狀之間的一些折衷:What is the difference between self-types and trait subclasses?

有關ScalaTest設計的一些背景知識,請參閱:http://www.artima.com/scalazine/articles/selfless_trait_pattern.html

+0

謝謝! ScalaTest鏈接正是我所需要的。 –

-1

這對於依賴注入Scalas語法。

this: <dependency> => 

它的字面意思this特徵取決於<dependency>特質。閱讀article瞭解更多信息。

1

我可能會寫MySetup的方法是這樣的:

import org.scalatest.Suite 
import org.scalatest.BeforeAndAfterEach 

trait MySetup extends BeforeAndAfterEach { this: Suite => 

    var service: String = _ 

    abstract override def beforeEach(): Unit = { 
    service = "apa" 
    super.beforeEach() 
    } 

    abstract override def afterEach(): Unit = { 

    try { 
     super.afterEach() // To be stackable, must call super.afterEach 
    } 
    finally { 
     service = "" 
    } 
    } 
} 

這樣的自我型較少侵入。邁克的回答是正確的。這個想法是允許特質疊加,所以你可以混合使用不同的特性,如果你願意,可以按不同的順序混合。另一個相關的文章是「可堆疊的特質模式」:

http://www.artima.com/scalazine/articles/stackable_trait_pattern.html

您也可以找到相關Scaladoc部分有用的例子:

http://www.scalatest.org/scaladoc-1.6.1/org/scalatest/FlatSpec.html#composingFixtures

注意我所說的super.afterEach了。爲了可堆疊,你需要在beforeEach和afterEach之間調用super。我嘗試這樣做,以便如果super.afterEach發生異常,你仍然會得到這種特性的後續行爲。 (雖然在這一點上你的套件可能會中止,但在這種情況下可能並不重要,但總的來說這是個好主意。)

+0

執行閱讀!然而,有一點讓我感到困惑。當使用AbstractSuit特性的Fixture覆蓋def時,它必須以抽象爲前綴。如上所述,在BeforeAndAfterEach上執行beforeEach覆蓋時,不需要「abstract」。爲什麼區別? –