【问题标题】:Getting rid of lateinit when converting Spring Java8 Junit test to Kotlin将 Spring Java8 Junit 测试转换为 Kotlin 时摆脱 lateinit
【发布时间】:2017-01-03 20:46:15
【问题描述】:

我正忙着将 Java8 Junit 测试转换为 Kotlin

Java8:

@ActiveProfiles("junit")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:META-INF/spring/applicationContext.xml"})
public class AuctionTest {

    @Autowired
    AccountProcessor ap;

    @Test
    @Rollback
    public void securityTest(){

用 Kotlin 重写,看起来是这样的:

@ActiveProfiles("junit")
@RunWith(SpringJUnit4ClassRunner::class)
@ContextConfiguration("classpath*:META-INF/spring/applicationContext.xml")
class AccountTest() {

    @Autowired
    lateinit var ap: AccountProcessor

    @Test
    @Rollback
    fun securityTest() {

上面的单元测试运行良好,但我想摆脱lateinit

这样重写:

@ActiveProfiles("junit")
@RunWith(SpringJUnit4ClassRunner::class)
@ContextConfiguration("classpath*:META-INF/spring/applicationContext.xml")
class AccountTest(@Autowired val ap: AccountProcessor) {

    @Test
    @Rollback
    fun securityTest() {

Junit 抱怨

java.lang.Exception: 测试类应该只有一个公共 零参数构造函数

在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.(SpringJUnit4ClassRunner.java:104) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native 方法)在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:29) 在 org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:21) 在 org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) 在 org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26) 在 org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59) 在 org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26) 在 org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:31) 在 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:96) 在 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) 在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

有没有办法解决这个问题,还是我坚持使用 lateinit @Autowires ?

【问题讨论】:

  • 1.将属性设置为 lateinit 并没有错。创建lateinit 关键字的原因是为了处理这种情况。我看不出有什么理由让你想摆脱 lateinit。 2. 读取异常信息时,需要有一个无参数构造函数,所以不可能有@Autowired 构造函数参数。
  • 如果不对 Junit 进行一些修补,我认为您想要的是不可能的。如果您确实想走这条路,您需要构建自己的Runner 来初始化spring,然后通过调用构造函数来实例化测试类。看看Parameterized,看看如何实例化一个需要参数的测试类。
  • 很公平,似乎最简单的方法是暂时将lateinit 留在其中。

标签: java spring junit kotlin


【解决方案1】:

如果 spring 组件注入处理器,你应该注释构造函数,而不是构造函数参数:

@Service
class AccountTest @Autowired constructor(val ap: AccountProcessor) {
}

Bit Junit 增加了对如何实现测试类的限制,并且无法以您想要的方式注入 bean。

ps。从 Spring 4.3 开始,您不再需要 @Autowired:

@Service
class AccountTest(val ap: AccountProcessor) {

【讨论】:

  • 是的,@Autowired constructor 是正确的做法,感谢您的指正。可惜我不能在单元测试中使用它,它看起来比列出一堆@Autowired 资源要干净得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多