Using property values in JUnit test classes without load whole Spring Boot application context

I have a Spring Boot Component as below

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class Client {

    @Value("${SecretKey}") private String secretKey;
    
    public void createAccount() {
        log.error("secretKey" + secretKey);
    }

}

How do I write a test class where Client class automatically use the resource/application.yaml in the test classpath, without loading the whole application context? I want to use like below :

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@Slf4j
@ExtendWith(SpringExtension.class)
public class ClientTest {

    @Autowired
    private Client client;

    @DisplayName("Create Client")
    @Test
    public void givenX_thenCreateAccount() throws Exception {
       client.createAccount();
    }

}

The test class above throws :

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.nerdility.payment.stripe.ClientTest': Unsatisfied dependency expressed through field 'client'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'Client' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

I don’t want to load the whole application context just for secretKey thing because it is expensive.

I also don’t want to create a constructor and manually give the key myself.

Answer

Main reason for this exception is without loading your class Client in springContext, you are trying to read it. So you are getting NoSuchBeanDefinitionException

You need to do 2 things.

  1. Load your class in context with class annotation @ContextConfiguration(classes = Client.class)
  2. Explicitly load you application.yaml from src folder as you are not having it in test/resource folder as @TestPropertySource(locations = "/application.yaml")

Leave a Reply

Your email address will not be published. Required fields are marked *