I use spring boot 2
I created a basic test
@RunWith(SpringJUnit4ClassRunner.class)
public class VehicleServiceImplTest {
private VehiculeServiceImpl service;
@Autowired
private VehicleRepository repository;
@Before
public void prepare() {
service = new VehiculeServiceImpl(repository);
}
@Test
public void test(){
}
}
I get
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'com.namur.service.VehicleServiceImplTest': Unsatisfied dependency
expressed through field 'repository'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.namur.repository.VehicleRepository'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
If i replace Autowired by MockBean it's working but I don't know why
If i replace Autowired by MockBean it's working but I don't know why
It works because @MockBean
replaces or adds a bean into the Spring context.
In your case, it adds a repository
mock in the Spring context.
So this could not throw any UnsatisfiedDependencyException
.
But that is not necessary what you need as you used initially @Autowired
that is designed to inject a bean from the context.
@Autowired
and @MockBean
are indeed two very different things that you never substitute for a same need.
As a side note, you should probably rethink the way which your test is built.
Actually you are using the SpringJUnit4ClassRunner
runner.
It means that you want to use the Spring container for your test.
It is a valid approach. But in this case, why do you create VehiculeServiceImpl outside the Spring container ?
service = new VehiculeServiceImpl(repository);
You should rather inject the service.
Note that creating a new instance of the class under test outside the containers is also a very valid approach.
We do it as we write plain unit tests. If you want to do it, don't use the Spring Boot runner, that by the way, makes tests slower.
It is because you have not supplied the test with any indication of what the spring context is hence there are no beans at all available to autowire.
By providing a @MockBean you are essentially providing a test context with a single existing bean which is a mock of the VehicleRepository class.
You can use the @SpringBootTest annotation which will load a spring context for you to use in your test. Then you should be able to @Autowire the actual repository:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class VehicleServiceImplTest {