Bohdan Myslyvchuk
Bohdan Myslyvchuk

Reputation: 1817

How to write integration/system test with Spring Boot to test service with repository

I have @Service in Spring Boot app which is parsing file and then storing it into DB using Spring Data JPA. I want to test this parsing with all logic of changing this mapping. So, for this I need to store mapping in DB in test.

@Service  
public class ParsingService {
    @Autowired
    private StoringInDBRepository storingInDBRepository;
}

@Repository
public interface StoringInDBRepository extends JpaRepository<MyEntity, String> {

The problem is that during test with annotation @SpringBootTest I don't want to load the whole context, but only my ParsingService. When I writing :

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ParsingService.class})
public class ParsingServiceTest{

    @Test
    public void someTest(){
    }
}

This test couldn't be initialized because I am not loading StoringInDBRepository in @SpringBootTest annotation. However I can do it, because StoringInDBRepository is an interface. Usage of @DataJpaTest according to javadoc will be correct only if I'm testing repository layer. Usage of @DataJpaTest and @SpringBootTest is not recommended.

How should I test such services? Thanks in advance.

Upvotes: 3

Views: 3307

Answers (2)

Bohdan Myslyvchuk
Bohdan Myslyvchuk

Reputation: 1817

So, after all investigations I found a couple solutions. I chose to enable repositories and service with

@SpringBootTest(classes = {ParsingService.class})
@EnableJpaRepositories(basePackages = "com.my.repository")
@EntityScan("com.my.entity")
@AutoConfigureDataJpa

This is a workaround. And I don't think it is the best. The other solution is to create a @TestConfiguration which will return your service and all to use @DataJpaTest annotation to enable repository classes. In this case you should use @SpringBootTest annotation

Upvotes: 5

Urosh T.
Urosh T.

Reputation: 3814

You could use a @SpyBean to get what you want. It is fairly easy to use.

However - You don't actually need to test it in that way. Because by having your application context tested, you are making sure all classes get injected/autowired as they should be. Then separately test the method on the service level with mocks. And lastly, use @DataJpaTest to test it in the repository/DB level.

So you decouple your tests nicely: integration tests / unit tests / repository tests

There is no need to tightly couple all those three things in one class or test method.

Upvotes: 2

Related Questions