【问题标题】:Is there a way to use Autowired constructor in JUnit test using Spring or Spring Boot?有没有办法在使用 Spring 或 Spring Boot 的 JUnit 测试中使用 Autowired 构造函数?
【发布时间】:2019-03-19 15:55:02
【问题描述】:

假设我有一个包含几个 Spring bean 的测试配置,它们实际上是模拟的,我想在 JUnit 测试套件中指定这些模拟的行为。

@Profile("TestProfile")
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = {
        "some.cool.package.*"})
public class IntegrationTestConfiguration {

    @Bean
    @Primary
    public Cool cool() {
        return Mockito.mock(Cool.class);
    }
}

// ...

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ActiveProfiles("TestProfile")
public class CoolIntegrationTest {

    private final Cool cool;

    @Autowired
    public CoolIntegrationTest(Cool cool) {
        this.cool = cool;
    }

    @Test
    public void testCoolBehavior {
        when(cool.calculateSomeCoolStuff()).thenReturn(42);
        // etc
    }
}

如果我运行这个测试,我会得到:

java.lang.Exception: Test class should have exactly one public zero-argument constructor

我知道在测试中使用 Autowired 字段等解决方法,但我想知道是否有办法在 JUnit 测试中使用 Autowired 注释?

【问题讨论】:

    标签: java spring junit integration-testing autowired


    【解决方案1】:

    问题不是自动装配,而是无参数构造函数。 JUnit 测试类应该有一个单一的、无参数的构造函数。要实现您的目标,您应该执行以下操作:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    @ActiveProfiles("TestProfile")
    @ContextConfiguration(classes = {IntegrationTestConfiguration.class})
    public class CoolIntegrationTest {
    
        @Autowired
        private final Cool cool;
    
        @Test
        public void testCoolBehavior {
            when(cool.calculateSomeCoolStuff()).thenReturn(42);
            // etc
        }
    }
    

    contextConfiguration 注解告诉 spring 使用哪个配置进行测试,自动装配字段而不是构造函数将允许你测试你的 spring bean。

    【讨论】:

      【解决方案2】:

      要使用 Spring 运行测试,您必须添加 @RunWith(SpringRunner.class) 并确保您的类已添加到类路径中。有几种方法可以做到这一点。 IE。 将类添加到 MVC 配置 @WebMvcTest({Class1.class, Class2.class}) 或使用 @ContextConfiguration

      但是我看到了你的代码,我想使用@Mock@MockBean 来模拟你的bean 会更容易。这会容易得多。

      【讨论】:

        【解决方案3】:

        JUnit 要求测试用例具有无参数构造函数,因此,由于您没有,异常发生在连接过程之前。

        所以构造函数自动装配在这种情况下不起作用。

        那该怎么办呢?

        有很多方法:

        最简单的(因为你有 spring)是利用@MockBean 注解:

        @RunWith(SpringRunner.class)
        @SpringBootTest
         ....
        class MyTest {
        
           @MockBean
           private Cool cool;
        
           @Test
           void testMe() {
              assert(cool!= null); // its a mock actually
           }
        }
        

        【讨论】:

          【解决方案4】:

          除了 args 构造函数之外,您还需要另外一个无参数构造函数。尝试添加它并检查此异常是否仍然发生。

          @Autowired
          public CoolIntegrationTest(Cool cool) {
                  this.cool = cool;
              }
          
          public CoolIntegrationTest() {}
          

          【讨论】:

          • 我已经尝试过这种方法并得到了其他异常:java.lang.IllegalArgumentException:测试类只能有一个构造函数
          • 这不行,因为测试类只能有一个构造函数
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-07-19
          • 2012-01-19
          • 2023-03-17
          • 2012-01-10
          • 2017-02-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多