2011-06-08 54 views
13

我需要填充我ScalaTest測試與來自Spring上下文@Autowired領域,但大多數Scalatest測試(例如FeatureSpec s不能由SpringJUnit4ClassRunner.class運行Java的,但你的要點)。如何整合ScalaTest同春

如何填充@Autowired領域從ApplicationContext爲ScalaTest?

class AdminLoginFeatureTest extends FeatureSpec with GivenWhenThen with ShouldMatchersForJUnit { 

    @Autowired val app: WebApplication = null 
    @Autowired val siteDAO: SiteDAO = null 

    feature("Admin Login") { 
    scenario("Correct username and password") {...} 

回答

26

使用TestContextManager,因爲這緩存了上下文,以便它們不會在每次測試時重建。它由類註釋配置。

@ContextConfiguration(
    locations = Array("myPackage.UnitTestSpringConfiguration"), 
    loader = classOf[AnnotationConfigContextLoader]) 
class AdminLoginFeatureTest extends FeatureSpec with GivenWhenThen with ShouldMatchers { 

    @Autowired val app: WebApplication = null 
    @Autowired val siteDAO: SiteDAO = null 
    new TestContextManager(this.getClass()).prepareTestInstance(this) 

    feature("Admin Login") { 
    scenario("Correct username and password") {...} 
    } 
} 
3

我試着使用鄧肯的回答與Spring 4 +斯卡拉2.11,我得到了以下錯誤:

java.lang.IllegalStateException: Test class [TestGateway] has been configured with @ContextConfiguration's 'locations' (or 'value') attribute {GatewayContextConfiguration}, but AnnotationConfigContextLoader does not support resource locations. 

配置ContextConfiguration,而不是字符串時,我不得不調整自己的代碼中使用一個類:

@ContextConfiguration(classes = Array(classOf[GatewayContextConfiguration]), 
         loader = classOf[AnnotationConfigContextLoader]) 
class TestGateway extends FlatSpec with Matchers { 

    @Autowired val gpClient: IGlobalPropsWSClient = null 

    new TestContextManager(this.getClass()).prepareTestInstance(this) 

    "Echo" should "return what it was sent." in { 
    val gateway = new CasaWsGateway 
    gateway.echo("This is a test") should be ("This is a test") 
    } 
} 
3

這裏是作爲一個可堆疊特性實現的版本(這樣你可以有自己的beforeAll()afterAll()方法,如果需要的話)使用TestContextManager來完成上下文生命週期。

我試過其他文章中建議的原始TestContextManager.prepareTestInstance()解決方案,但注意到我的上下文沒有關閉,導致副作用,並在使用sbt控制檯進行每次連續測試後累積垃圾。

@ContextConfiguration(classes = Array(classOf[SomeConfiguration])) 
class SomeTestSpec extends FlatSpec with TestContextManagement { 

    // Use standard Autowired Spring annotation to inject necessary dependencies 
    // Note that Spring will inject val (read-only) fields 
    @Autowired 
    val someDependency: SomeClass = null 

    "Some test" should "verify something" in { 
    // Test implementation that uses injected dependency 
    } 

} 

TestContextManagement Gist

import org.scalatest.{BeforeAndAfterAll, Suite} 
import org.springframework.core.annotation.{AnnotatedElementUtils, AnnotationAttributes} 
import org.springframework.test.annotation.DirtiesContext 
import org.springframework.test.context.{TestContext, TestContextManager} 
import org.springframework.test.context.support.DirtiesContextTestExecutionListener 
import org.springframework.util.Assert 

/** 
* Manages Spring test contexts via a TestContextManager. 
* 
* Implemented as a stackable trait that uses beforeAll() and afterAll() hooks to invoke initialization 
* and destruction logic, respectively. 
* Test contexts are marked dirty, and hence cleaned up, after all test methods have executed. 
* There is currently no support for indicating that a test method dirties a context. 
* 
* @see org.springframework.test.context.TestContextManager 
*/ 
trait TestContextManagement extends BeforeAndAfterAll { this: Suite => 

    private val testContextManager: TestContextManager = new TestContextManager(this.getClass) 

    abstract override def beforeAll(): Unit = { 
    super.beforeAll 
    testContextManager.registerTestExecutionListeners(AlwaysDirtiesContextTestExecutionListener) 
    testContextManager.beforeTestClass 
    testContextManager.prepareTestInstance(this) 
    } 

    abstract override def afterAll(): Unit = { 
    testContextManager.afterTestClass 
    super.afterAll 
    } 
} 

/** 
* Test execution listener that always dirties the context to ensure that contexts get cleaned after test execution. 
* 
* Note that this class dirties the context after all test methods have run. 
*/ 
protected object AlwaysDirtiesContextTestExecutionListener extends DirtiesContextTestExecutionListener { 

    @throws(classOf[Exception]) 
    override def afterTestClass(testContext: TestContext) { 
    val testClass: Class[_] = testContext.getTestClass 
    Assert.notNull(testClass, "The test class of the supplied TestContext must not be null") 

    val annotationType: String = classOf[DirtiesContext].getName 
    val annAttrs: AnnotationAttributes = AnnotatedElementUtils.getAnnotationAttributes(testClass, annotationType) 
    val hierarchyMode: DirtiesContext.HierarchyMode = if ((annAttrs == null)) null else annAttrs.getEnum[DirtiesContext.HierarchyMode]("hierarchyMode") 
    dirtyContext(testContext, hierarchyMode) 
    } 
} 
0

如果您在使用Spring啓動時,您可以使用TestContextManager來(如其他意見建議)和@SpringBootTest註解。

這是我的測試與scalaTest春季啓動控制器:

@RunWith(classOf[SpringRunner]) 
@SpringBootTest(webEnvironment = RANDOM_PORT) 
class CustomerControllerIT extends FeatureSpec with GivenWhenThen with Matchers { 

    @Autowired 
    var testRestTemplate: TestRestTemplate = _ 
    new TestContextManager(this.getClass).prepareTestInstance(this) 

    @LocalServerPort 
    val randomServerPort: Integer = null 

    val baseUrl = s"http://localhost:$randomServerPort" 

    feature("Customer controller") { 

    scenario("Find customer by id") { 

     Given("a customer id") 
     val id = 1 

     When("a request to /customers/{id} is sent") 
     val url = s"$baseUrl/customers/$id" 
     val response = testRestTemplate.getForEntity(url, classOf[Customer]) 

     Then("we get a response with the customer in the body") 
     response.getBody.getId shouldBe 1 
     response.getBody.getName shouldBe "Bob" 

    } 

    } 

} 

這裏有一個關於如何做集成測試和單元測試彈簧引導和ScalaTest後: ignaciosuay.com/testing-spring-boot-with-scalatest/