简体   繁体   中英

Error org.springframework.beans.factory.UnsatisfiedDependencyException

I have a problem that prevents me from moving forward and I don't know how to solve it. I have a class called Validator where I store validation functions and I need to do unit tests for each one and validate its functionality, but there are some of them that use the Spring Environment instance in which it accesses the properties file. If I do "normal" unit tests, whenever I call the function where this feature is implemented, it returns me Environment is null. I have tried using @Autowired instead of instantiating with new in the test class, the use of @RunWith(SpringRunner.class) and since the test classes and the function classes are in different packages I have also used the @ComponentScan and it gives me an error... What am I doing wrong or what am I doing wrong?

I have the code of the Validator class in this way:

@Component
public class Validator {
        
    @Autowired
    public Environment env;
    
    public CodRespuestaWS validateTypeOperation(TypeOperation typeOperation, String operation) {
        
        String response = env.getProperty(typeOperation.toString() + "." + operation);
        if (OK.equalsIgnoreCase(response)) {
            return new CodResponseWS();
        }
        return new CodResponseWS(CodResponseWS.ER100, typeOperation.toString()+" not allowed:" + operation);
    }

} 

And in the test I do it this way:

@ComponentScan(basePackages = "com.functions.validators")
@RunWith(SpringRunner.class)

public class ValidateRequestHigh {

    RequestHigh requestHigh = new RequestHigh();
    CodResponseWS response;
    @Autowired Validator validator;
    
    HighValidator highValidator = new HighValidator();
    UserData userData = new UserData();
    
    
    @Test
    public void test() throws Exception {
        response = validator.validateTypeOperation(TypeOperation.typeOperationHigh, "high");
        System.out.println(response.getCodResponse());
    }
}

The problem that I mentioned before the NULL, is that when executing the test it did not even reach the print that I have set, but rather it stayed on the line

String response = env.getProperty(typeOperation.toString() + "." + operation);

And it marked the error that env was NULL and now it returns a different one

And the error that returns me now is:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'functiontest.unittest.ValidateRequestHighTest': Unsatisfied dependency expressed through field 'validator'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.functions.validators.Validator' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

I guess it's already understood, but I'll detail it more just in case, the functions are in

src/main/java/com.functions.validators/Validators.java

and the tests

src/main/test/functiontest.unittest/ValidateRequestHighTest.java

I am using version 5.1.2.RELEASE of SpringBoot and JUnit 4

Using field injection makes Validator class impossible to be unit tested because it provides no way to pass the Environment instance to it. but you can spin up the whole application context and configure it to do dependency injection stuff using @SpringBootTest which is not a unit test but integration test.

if I do "normal" unit tests, whenever I call the function where this feature is implemented, it returns me Environment is null.

Because when you use new to instantiate a bean its not a Spring managed bean anymore and its dependencies are not resolved.

I have tried using @Autowired instead of instantiating with new in the test class, the use of @RunWith(SpringRunner.class) and since the test classes and the function classes are in different packages I have also used the @ComponentScan and it gives me an error

You should also add SpringBootTest annotation for loading into application context.

If you want to really unit test your class you don't need application context instead do the following

Change the Validator class like:

@Component
public class Validator {

  
  private Environment env;

  public Validator(Environment env) {
    this.env = env;
  }

....
}

And for unit testing it do:

public class ValidatorTest {

  Validator validator;
  MockEnvironment environment;

  @Before
  public void setUp() {
    environment = new MockEnvironment();
    environment.setProperty("key1", "value1");
    //...
    environment.setProperty("keyn", "valuen");
    validator = new Validator(environment);
  }

  @Test
  public void test() {
    // test stuff
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM