简体   繁体   中英

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?

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

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