Lansorian
Lansorian

Reputation: 179

Why @Autowired raises UnsatisfiedDependencyException, even the class does not implement any interface?

Here is the class I want to test

@Component
public class PermissionCheck {

    @Autowired
    private MyEntityRepository myEntityRepository;

    public boolean hasPermission(int myEntityID) {
        MyEntity myEntity = myEntityRepository.findById(myEntityId);
        return myEntity != null;
    }
}

Here is the test class

@RunWith(SpringRunner.class)
public class PermissionCheckTests {

    @Autowired                                     // you need to autowire
    private PermissionCheck permissionCheck;       // and it uses @MockBean dependency

    @MockBean                                      // if no such @MockBean exists
    private MyEntityRepository myEntityRepository; // the real implementation is used

    @Test
    public void shouldHasPermission() {
        MyEntity myEntity = new MyEntity();

        when(this.myEntityRepository.findById(any())).thenReturn(myEntity);
        assertTrue(this.permissionCheck.hasPermission(0));
    }
}

And when I run this test I got

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'PermissionCheckTests': 
Unsatisfied dependency expressed through field 'permissionCheck'; 
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'PermissionCheck' available: 
expected at least 1 bean which qualifies as autowire candidate. 
Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true), 
@org.springframework.beans.factory.annotation.Qualifier(value="")}

From other SO questions, such as this one, I see that this happens when the target class implements an interface. But as we can see from the code, PermissionCheck does not implement any interface, so why is the exception still thrown?

Does that mean I have to create an interface, @Autowired it and let PermissionCheck implement it? It seems redundant to me, since I don't see why I need such an interface. Is there a way to make it work without creating a new interface which I will solely use for this purpose?

Upvotes: 1

Views: 875

Answers (1)

Domenico Sibilio
Domenico Sibilio

Reputation: 1387

@RunWith(SpringRunner.class) does not automatically load your configurations/beans/properties unless accompanied with annotations that specifically do that, such as @ContextConfiguration and @TestPropertySource.

If yours is a Spring Boot application and you want to load the whole context along with all properties, you can simply add the @SpringBootTest annotation to your test class.

References:

Upvotes: 1

Related Questions