Is there a way to use Autowired constructor in JUnit test using Spring or Spring Boot?

spring boot rest controller unit test example
spring boot end-to-end test
spring boot unit test
spring boot mockito test example
unit testing spring boot microservices
inject spring bean in junit test
spring boot test mock interceptor
constructor injection junit test

Assume, that I have a test configuration with several Spring beans, that are actually mocked and I want to specify the behavior of those mocks inside JUnit test suite.

@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
    }
}

If I run this test I will get:

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

I know the workaround like use Autowired fields in tests, but I wonder if there a way to use Autowired annotation in JUnit tests?

It's not the autowiring that's the problem, it's the no-arg constructor. JUnit test classes should have a single, no argument constructor. To achieve what you are attempting to do, you should do the following:

@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
    }
}

The contextConfiguration annotation tells spring which config to use for the test, and autowiring the field instead of the constructor will allow you to test your spring bean.

Unit Testing with Spring Boot, In this tutorial we'll learn how to build testable Spring beans and get to know the For the unit test in this tutorial, we'll use JUnit Jupiter (JUnit 5), If you have written tests with Spring or Spring Boot in the past, you'll to add the @​Autowired annotation to the constructor for Spring to find the constructor. Trouble with Login using Spring Boot and JDBC Security. spring,spring-security,spring-boot. There are 2 things flawed in your setup. You should post to /login instead of /j_spring_security_check as that is the new URL when using java config (and in Spring 4 for XML config also). You have set the usernameParameter to name and your form still has

To run a test using Spring you have to add @RunWith(SpringRunner.class) and make sure that your class is added to the classpath. There are a few ways to do it. I.e. Add class to MVC configuration @WebMvcTest({Class1.class, Class2.class}) or use @ContextConfiguration.

But I see your code, I suppose that it would be easier just use @Mock or @MockBean to mock your beans. It will be much easier.

Testing improvements in Spring Boot 1.4, The easiest way to unit test any Spring @Component is to not involve Spring at all! use constructor injections as you no longer need to use @Autowired . @​RunWith(SpringRunner.class) tells JUnit to run using Spring's  In this article, we will discuss a very important Spring dependency injection annotation that is a @Autowired annotation. We can use the @Autowired to mark a dependency which Spring is going to resolve and inject. We can use this annotation with a constructor, setter, or field injection.

JUnit requires the Test case to have a no-arg constructor, so, since you don't have one, the exception happens before the wiring process.

So Constructor-Autowiring just doesn't work in this case.

So what to do?

There are many approaches:

The easiest one (since you have spring) is taking advantage of @MockBean annotation:

@RunWith(SpringRunner.class)
@SpringBootTest
 ....
class MyTest {

   @MockBean
   private Cool cool;

   @Test
   void testMe() {
      assert(cool!= null); // its a mock actually
   }
}

Constructor Dependency Injection in Spring, Quick and practical intro to Constructor based injection with Spring. Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2: >> CHECK OUT THE COURSE Wiring in Spring: @Autowired, @Resource and @Inject ways to use Constructor-Based Dependency Injection using Spring  Another option is to turn on this feature by default and provide a way to opt out of it, but that would potentially be a breaking change for some users -- for example, if a test class constructor previously declared an @Autowired parameter alongside something like TestInfo from JUnit Jupiter.

Besides args constructor you need to have additional one no-args constructor. Try add it and check if this exception still occurcs.

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

public CoolIntegrationTest() {}

Wiring in Spring: @Autowired, @Resource and @Inject, Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2: The examples will focus on how to use the three injection annotations Quick and practical intro to Constructor based injection with Spring. The test will still pass because if the @Resource annotation does not receive a  In this case they must be defined in the xml or java config file you provide, so that it can be injected by Spring. Best practice says you create a smaller config file for that test case. This way you are not creating a bunch of beans for stuff that is not under test. You can also use a framework like Mockito to inject mocks rather than real

Mastering Software Testing with JUnit 5: Comprehensive guide to , the diagram here). This is the way shown in the example earlier. As of Spring 4.3, it is not required anymore to annotate the constructor with Different ways of dependency injection (Autowired) in Spring Execution of test using Spring Boot. Take note that you need to exclude the default JUnit from the spring-boot-starter-test dependency. The junit-jupiter-engine dependency is for JUnit 5. Create a Java REST API With Spring Boot for

Developing Java Applications with Spring and Spring Boot: , Practical Spring and Spring Boot solutions for building effective applications will disable the general Spring Boot autoconfiguration, and instead, use Spring Boot's But for test code where constructors are limited due to JUnit, autowiring as  Spring Boot: Unit Testing and Mocking With Mockito and JUnit In this post we take an in-depth look at how to create effective unit tests in Spring Boot using JUnit and Mockito. Read on for the

Kotlin Cookbook: A Problem-Focused Approach, Spring also advocates the use of JUnit 5 for tests. Injecting dependencies by using constructor arguments in JUnit 5 @DataJpaTest class RepositoriesTests @​Autowired constructor( val entityManager: TestEntityManager, val userRepository​: UserRepository, val SpringBootTest(webEnvironment = SpringBootTest. In Spring framework, bean autowiring by constructor is similar to byType, but applies to constructor arguments. In autowire enabled bean, it look for class type of constructor arguments, and then do a autowire by type on all constructor arguments. Please note that if there isn’t exactly one bean of the constructor argument type in the

Comments
  • I've tried this approach and got other exception: java.lang.IllegalArgumentException: Test class can only have one constructor
  • This will not work, because test class can have only one constructor