I have some Repository
-beans in my project. I wire the collection of this repos to some of my services and iteratively fetch data from each of them. But in my unit-tests I want to exclude all of these repositories (real implementations) from Spring context and use only fake one. How do I achieve it?

- 2,802
- 6
- 38
- 60
3 Answers
Testing the Auto-Configuration:
Let’s create a very simple example to test our auto-configuration. We will create an entity class called MyUser, and a MyUserRepository interface using Spring Data:
@Entity
public class MyUser {
@Id
private String email;
// standard constructor, getters, setters
}
public interface MyUserRepository
extends JpaRepository<MyUser, String> { }
To enable auto-configuration, we can use one of the @SpringBootApplication
or @EnableAutoConfiguration
annotations:
@SpringBootApplication
public class AutoconfigurationApplication {
public static void main(String[] args) {
SpringApplication.run(AutoconfigurationApplication.class, args);
}
}
Next, let’s write a JUnit test that saves a MyUser entity:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(
classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(
basePackages = { "com.baeldung.autoconfiguration.example" })
public class AutoconfigurationTest {
@Autowired
private MyUserRepository userRepository;
@Test
public void whenSaveUser_thenOk() {
MyUser user = new MyUser("user@email.com");
userRepository.save(user);
}
}
Since we have not defined our DataSource configuration, the application will use the auto-configuration we have created to connect to a MySQL database called myDb
.
The connection string contains the createDatabaseIfNotExist=true
property, so the database does not need to exist. However, the user mysqluser or the one specified through the mysql.user property if it is present, needs to be created.
We can check the application log to see that the MySQL data source is being used:
web - 2017-04-12 00:01:33,956 [main] INFO o.s.j.d.DriverManagerDataSource - Loaded JDBC driver: com.mysql.cj.jdbc.Driver
Disabling Auto-Configuration Classes
If we wanted to exclude the auto-configuration from being loaded, we could add the @EnableAutoConfiguration
annotation with exclude
or excludeName
attribute to a configuration class:
@Configuration
@EnableAutoConfiguration(
exclude={MySQLAutoconfiguration.class})
public class AutoconfigurationApplication {
//...
}
Another option to disable specific auto-configurations is by setting the spring.autoconfigure.exclude
property:
spring.autoconfigure.exclude=com.baeldung.autoconfiguration.MySQLAutoconfiguration
Resource Link: Create a Custom Auto-Configuration with Spring Boot
Solution#2:
Matt C also given a solution in this tutorial:How to exclude *AutoConfiguration classes in Spring Boot JUnit tests?.

- 28,384
- 14
- 74
- 132
Spring context is really rarely used in unit testing. First question that you should ask yourself: "What unit of work I want to test?". After you get an answer, you should test it in isolation. You don't need spring context here. Spring context usually needed in integration tests. Unit tests must not depend on context.
You could use @Mock
and @InjectMocks
annotations, provided by Mockito
. For example:
public class SomeServiceTest {
@InjectMocks
SomeService someService;
@Mock
PersonRepository personRepository;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
@Test
public void testFindPersonExpectOk(){
String name = "John";
String secondName = "Doe";
// Configure the behavior for mocked repository
Person person = new Person(name, secondName);
when(personRepository.findByNameAndSecondName(name,
secondName).thenReturn(person);
// Call some method in testing service
Person fetchedPerson = someService.findUser(name, secondName);
// Check that everything is fine
assertThat(fetchedPerson.getName, is(name));
}
}

- 299
- 1
- 6
Here's the solution:
@SpringBootApplication
@ComponentScan(basePackages = "my.base.package",
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "my.base.package.repositories.*.*"))
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Bean
public Repository someFakeRepository() {
return new FakeRepository();
}
}
And then the test-class:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class ApplicationTests {
@Autowired
private Repository fakeRepository;
// tests
}
So I've replaced all real beans with the test-one.

- 2,802
- 6
- 38
- 60