我需要使用Spring上下文中的@Autowired
字段填充我的ScalaTest测试,但大多数Scalatest测试(例如FeatureSpec
s不能由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") {...}
答案 0 :(得分: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") {...}
}
}
答案 1 :(得分:3)
我尝试使用Duncan对Spring 4 + Scala 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" )
}
}
答案 2 :(得分:3)
此处' sa实现为可堆叠特征(以便您可以使用beforeAll()
和afterAll()
方法(如果需要)使用TestContextManager
来完成上下文生命周期
我尝试了其他帖子中建议的原始TestContextManager.prepareTestInstance()
解决方案,但注意到我的上下文没有关闭,导致副作用并在每次连续测试运行后使用sbt控制台累积垃圾。< / p>
@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
}
}
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)
}
}
答案 3 :(得分:1)
如果您使用的是Spring引导,则可以使用TestContextManager(如其他建议的注释)和@SpringBootTest注释。
这是我使用scalaTest和spring boot测试控制器的方法:
@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"
}
}
}
这里有一篇关于如何使用spring boot和ScalaTest进行集成测试和单元测试的帖子: ignaciosuay.com/testing-spring-boot-with-scalatest/