15

ScalaTestテストに@AutowiredSpringコンテキストのフィールドを入力する必要がありますが、ほとんどのScalatestテスト(たとえば、 -FeatureSpecで実行することはできません)SpringJUnit4ClassRunner.class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="myPackage.UnitTestSpringConfiguration", loader=AnnotationConfigContextLoader.class)
public class AdminLoginTest {
    @Autowired private WebApplication app;
    @Autowired private SiteDAO siteDAO;

(Javaですが、要点はわかります)。

ScalaTest@Autowiredのフィールドにデータを入力するにはどうすればよいですか?ApplicationContext

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") {...}
4

4 に答える 4

28

を使用します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") {...}
  }
}
于 2011-06-08T17:38:23.743 に答える
4

これは、コンテキストライフサイクルを完了するために使用するスタック可能なトレイトとして実装されたバージョンです(必要に応じて、独自のメソッド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の要点

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)
  }
}
于 2015-03-22T02:26:08.923 に答える
3

Spring 4 + Scala 2.11でDuncanの回答を使用しようとしましたが、次のエラーが発生しました。

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" )
  }
}
于 2014-08-07T15:59:21.620 に答える
3

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/

于 2017-12-18T15:30:26.777 に答える