data.sql is not executed during unit test

Viewed 649

I am implementing a unit test for a basic CRUD API. I have a class called Classified which includes an instance of a class named Category inside it. Both of them have their own databases. To initialize Category database I created a "data.sql" file under resources folder. It worked splendidly during normal execution but it is not being executed when I run my test. I am using h2 in-memory database.

data.sql content:

insert into CATEGORY values (1, 'Real Estate');
insert into CATEGORY values (2, 'Vehicle');
insert into CATEGORY values (3, 'Shopping');
insert into CATEGORY values (4, 'Other');

test class:

@RunWith(SpringJUnit4ClassRunner.class)
public class ClassifiedServiceTest {
@Mock
private ClassifiedRepository classifiedRepository;
@Mock
private ClassifiedHistoryRepository classifiedHistoryRepository;
@Mock
private CategoryRepository categoryRepository;
@InjectMocks
private ClassifiedService classifiedService;

@Test
public void createClassifiedTest() throws FileNotFoundException {
    // This method throws an exception related to CATEGORY table being empty
    }
}

I tried adding @Sql("data.sql") to Test class but then I got

org.springframework.test.context.transaction.TestContextTransactionUtils - Caught exception while retrieving DataSource for test context [DefaultTestContext@1189dd52 testClass = ClassifiedServiceTest, testInstance = com.sahibinden.codecase.services.ClassifiedServiceTest@1133ec6e, testMethod = createAndDeactivateClassifiedTest@ClassifiedServiceTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@36bc55de testClass = ClassifiedServiceTest, locations = '{}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@a4102b8, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7a52f2a2, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@75f32542, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@229d10bd], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false, 'org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.mocks' -> org.mockito.internal.configuration.InjectingAnnotationEngine$$Lambda$113/0x0000000800da41d8@355e34c7]]
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'dataSource' 
available

How can I configure my test class to run data.sql and populate the database before running these tests

2 Answers

For this, you should use @SpringBootTest to let Spring Boot autoconfigure your embedded datasource using H2. Spring Boot will then execute your schema.sql and data.sql to setup your H2 database automatically. If you use @SpringBootTest, you have to inject your bean using @Autowired instead of @InjectMocks and you don't need to mock others beans.

@SpringBootTest
public class ClassifiedServiceTest {

@Autowired
private ClassifiedService classifiedService;

@Test
public void createClassifiedTest() throws FileNotFoundException {
    // This method throws an exception related to CATEGORY table being empty
    }
}

You can also use slice testing if starting your Spring boot app is too long. For that, you can do :

@DataJpaTest
@Import(ClassifiedServiceImpl.class) // You need the implementation here 
public class ClassifiedServiceTest {

@Autowired
private ClassifiedService classifiedService;

@Test
public void createClassifiedTest() throws FileNotFoundException {
    // This method throws an exception related to CATEGORY table being empty
    }
}

It will only setup all the things needed to using JPA and load your ClassifiedService in the application context.

Like says Farid you cannot use Spring data in Unit Test but in Integration Test instead with

@SpringBootTest

for mount SpringBoot context

Related