matthieusb
matthieusb

Reputation: 505

Best approach for unit testing with data

I have a lot of DAO classes I need to test on a Spring project.

I am already using DBUnit to mock my database, however I use the @Before annotation to create objects and compare them after tests on create/update/delete operations.

@DatabaseSetup(value = { "/db_data/dao/common.xml", "/db_data/dao/myDAOCommonTest.xml" })
@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
public class MyDAOImplTest extends AbstractDaoTU {

  @Autowired
    private MyDAO myDAO;

    private Set<ClassNeeded> objectsNeeded = new HashSet<>();
    private ClassOne classOne;
    private ClassTwo classTwo;

    private ClassThree classThree;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        this.objectsNeeded.add(somethingComingFromTheMotherClass);

        this.classOne = new ClassOne();
        this.classOne.setIdClassOne(1L)
    this.classOne.setObjectsNeeded(this.objectsNeeded);
        // ... Many other sets

        this.classTwo = new ClassTwo();
        this.classTwo.setIdClassTwo(1L);
    this.classTwo.setClassOne(this.classOne);
    // ... Many other sets

    // ... Other sets follow for a lot of other objects
    }

  @Test
  public void testOne {
    // ...
  }

  // ... Other tests follow
}

I am using an ORM (Hibernate in this case), and most objects are inter-dependent. My dao functions mostly need complete objects to be called, so I must create the objects before testing.

My questions are the following :

Thanks for your help !

Upvotes: 2

Views: 320

Answers (2)

Stanislav Bashkyrtsev
Stanislav Bashkyrtsev

Reputation: 15308

  1. DB Unit complicates the maintenance of the tests as it increases the number of places that need updates when something changes. Additionally it separates the data preparation from the tests too much so it's hard to find which of the data relates to which tests.
  2. Ideally each test prepares data for itself. This removes global state and keeps related things together.

To prepare the data just create entities and save them in the very same test. You can use randomization and transaction rollbacks to isolate the tests. Here is an example from one of my projects:

@Test public void returnsExperimentAsItWasSaved() {
    Experiment original = Experiment.random();
    experimentRepository.save(original);
    flushToDbAndClearCache();

    Experiment fromDb = experimentRepository.findOne(original.getExperimentId());
    assertReflectionEquals(original, fromDb);
}

Note, that the very same DAO class is used to prepare the data.

Upvotes: 3

GeertPt
GeertPt

Reputation: 17846

The best way is to develop your tests as you would develop your code: refactor to minimize duplication, extract reusable services, etc.

So, you'll probably create some TestCaseFactory that chains up a whole set of objects and saves them using your actual DAO's. Then, you can call them from an @Before as you did. If you need a lot of different sets of objects, you can create different methods or a parameter object etc.

And do a cleanup of all test data in an @After.

Upvotes: 1

Related Questions