rocker
rocker

Reputation: 69

Java Mock data base for testing Spring application

I have made simple application for study perpose and i want to write some unit/intagration tests. I read some information about that i can mock data base insted of create new db for tests. I will copy the code which a write. I hope that some one will explain me how to mock database.

public class UserServiceImpl implements UserService {

    @Autowired
    private UserOptionsDao uod;

    @Override
    public User getUser(int id) throws Exception {
        if (id < 1) {
            throw new InvalidParameterException();
        }
        return uod.getUser(id);
    }

    @Override
    public User changeUserEmail(int id, String email) {
        if (id < 1) {
            throw new InvalidParameterException();
        }

        String[] emailParts = email.split("@");
        if (emailParts[0].length() < 5) {
            throw new InvalidParameterException();
        } else if (!emailParts[1].equals("email.com")) {
            throw new InvalidParameterException();
        }

        return uod.changeUserEmail(id, email);
    }

This above i a part of the code that i want to test with the mock data base.

Upvotes: 3

Views: 1892

Answers (2)

Brad
Brad

Reputation: 2320

Generally you have three options:

  1. Mock the data returned by UserOptionsDao as @Betlista suggested, thus creating a "fake" DAO object.
  2. Use an in-memory database like HSQLDB to create a database with mock data when the test starts, or
  3. Use something like a Docker container to spin up an instance of MySQL or the like and populate it with data, so you can restart it as necessary.

None of these solutions are perfect.

With #1, your test will skip the intermediate steps of authenticating to the database and looking for data. That leaves a part of your code untested, and as they say, "the devil is in the details." Often people run into problems when they mock DAO's like this when they try to deploy.

With #2, you connect to an actual database, but you have to make sure that either you are using the exact same type of database in your production code or something compatible. It also makes debugging a pain because you have to pause the test to see the contents of the database if something goes wrong.

With #3, you avoid all the problems with #1 and #2, but then you have to wire up all the Docker stuff. (I'm doing this right now, and I'm having problems too). The advantage, though, is that like #2 you can set up all of your test data at once, and be guaranteed that the production database you choose will be exactly the same as your unit test.

In your case, I would go with #2 since the application is for study purposes. Yes, I know this is a long-winded answer, but as you gain experience, you will probably want to know how to "scale up."

Upvotes: 3

Betlista
Betlista

Reputation: 10547

What you can do very easily is to have your implementation of UserOptionsDao in test package and set this one to UserServiceImpl. This new implementation can return fixed set of data for example...

This is a highlevel idea. You probably do not want to have many implementations (different for each test in general), so you should use some mocking framework like Mockito or EasyMock, look at the documentation for more details.

Upvotes: 1

Related Questions