Abbas Torabi
Abbas Torabi

Reputation: 255

Test in spring boot without effect on database

i'm trying to test my service layer (actually insert) without any effect on my database. here in my code:

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class StateServiceTest {

@Autowired
private StateService stateService;

@Test
public void createState() {
    State state = State.builder()
            .id(null)
            .name("testState")
            .code("21")
            .build();

    Object mCreatedState = stateService.create(state);
    assertThat(mCreatedState).isNotNull().isNotInstanceOf(Exception.class);
    }

}

use @Transactional probably solved my problem and test data doesn't insert to database, but still has effect on my database.

it means that if the inserted data exist in database or is duplicate (for unique column) , I got error duplicate entry key.

Is there any way to test my service and dao layer without effect on my database? or I should use test database like h2 (in memory) ?

Upvotes: 2

Views: 2926

Answers (3)

Abbas Torabi
Abbas Torabi

Reputation: 255

Finally I found the best solution.

After I read different notes, I think the best solution is: Not to use in memory databases like H2 or Fongo & if you really want this you should use Docker container like your main database.

That's because memory databases may have not all behaviors same as your main database as below :

1- Postgres has powerful features like window functions and JSON data types which are not supported by H2

2- For instance, we wanted to use MySQL’s unix_timestamp() function to be independent of the different time zones where our MySQL database servers are running. We want to prevent subtle inaccuracies. But this function doesn’t exist in H2, so we couldn’t use them

And ...

But if we use the same database like main database(Docker container), our test is so improved and finally we prevent most database bugs appear after project build or deploy on main(final) database.

Read below references may help you :

1- https://phauer.com/2017/dont-use-in-memory-databases-tests-h2/

2- https://medium.com/@sanchezdale/using-a-containerized-database-for-testing-spring-boot-applications-56ad38d39e15

hope to help someone.

Upvotes: 0

ardhani
ardhani

Reputation: 333

It is always better not to touch any of the existing infrastructures while testing. Connecting to databases will not only have unexpected behavior based not the values provided bust also adds time to the total execution time.

If DAO layer testing in itself is a use case then go ahead with H2, which lets you do all DB operations without any effect. Also running whole test suite multiple tests concurrently doesn't affect each other.

The downside of H2 is you have a separate copy of the DB schema, which could add to the project maintenance.

It's always a best practice to Mock external services.

Upvotes: 1

Priyak Dey
Priyak Dey

Reputation: 1367

If you want to test your service class without. affect on the database, it means you are trying to do an integration test for your service layer.

One of the options Spring Provides is @TestPropertSource. you can Override any property here, define new properties, or define a location of a new .properties/.yml file.

You can include h2 in your class as test scope, provide a new application-test.yml file under src/test/resources. Define the data source properties there to point to the h2 database and continue with your test.

Below are some blogs regarding the same:

There is another way called TestContaniers which spins up a db container. I personally have not used this but read about it. A good starting point to read more about them are :

Upvotes: 2

Related Questions