Unit testing code using a database

I’m interested to know what kind of approach people take when developing automated unit tests that use a database.

You install the QA database (known starting point) before starting the test suite.

OR

Are you creating a database stub that is idle when a database call is made?

EDIT: A related question, but not a duplicate, albeit very important for the question in question: How can I maintain unit-test repeatability?

+41
unit testing
Dec 24 '08 at 11:00
source share
11 answers

The "database stub" that is inside is usually called a "fake repository" or a "false repository." This is a good idea. You can program them manually (not hard for simple cases) or use a framework like Rhino Mocks to create them. You do not speak what language you work. Rhino mocks for .Net.

If you use mock repositories, you can run tests against code that works with data without actually using the database for the data. This makes the tests very fast, which is good.

Of course, you still have to test the real repository at a certain stage, and this is more of a problem. These tests will run slower because they use a real database. Some of them would then be classified as "integration tests" rather than unit tests due to problems with speed and dependency.

I am not against what you call it, but it is a good idea that these tests be separate.

A good idea here for data consistency is to start a db transaction before your test and then roll back. Thus, the state of the database returns to what it was before the test.

+29
Dec 24 '08 at 11:23
source share

If you use NHibernate, you can easily test the SQLite database in memory , which is very fast.

+12
Dec 24 '08 at 11:27
source share

We do a few tricks:

edit: We have separate databases for each user. Our builds server also has its own database. The cost of additional hard drives is much less than the cost of developers influencing other tests.

  • Our application can generate tables and perform update steps themselves (without separate db scripts). This helps our client, because he only needs to go into the WAR file, and he did it. The application scans the database and executes any DDL instructions necessary to run the rest of the Spring context.
  • Our test suite has code that unloads the Spring context, deletes the database, and restarts the context with a clean database. We can optionally disable this if we like
  • All our database / SQL unittests are Spring Transaction Integration Tests. This means that after the test is completed, transactions roll back, and other unittests will again look for a clean database.

In addition to this, we all try to do our prototyping as much as possible, because unittests are really not designed for test integration. Therefore, try to separate your service server from the DAO level. It also helps you find problems more easily because you isolated everything.

At some point, I believe that you need to access the database, because this is not the ideal / academic world we live in :-)

+3
Dec 24 '08 at 11:06
source share

It depends on the case, but on legacy systems in which I do not want to stub the database, I often present an interface, say IFooDBManager, which has methods that return ADO.Net objects, such as data tables or data sets. Of course, this should not be an interface, but it can be a virtual method, for example. Then in my tests I use a small API with a smooth interface that I created a long time ago, I use it to create datasets and tables and populate them with test values ​​so that I can return them from my fakes.

The free interface looks something like this:

return DataTableBuilder.Create() .DefineColumns("a, b") .AddRow().SetValue("a", 1).SetValue("b", 2).DoneWithRow() .AddRow().SetValue("a", 10).SetValue("b", 20).DoneWithRow() .Table 

As I said, this is only one of the approaches that I use, and this is mainly for legacy systems, where I do not want to introduce new dependencies on the operation of frames, etc. This, however, is a technique that I have not seen many other people, so I thought it was worth mentioning.

EDIT: I forgot to make it clear that this is to create a database, so the interaction with the database is not checked in this case. The actual interaction will occur in a particular implementation of IFooDBManager to verify that something else is required.

In addition, not all methods on such an interface, of course, return things, there are also ways to write to the database, and they are usually checked by testing the interaction in RhinoMocks, where I set expectations for these methods.

+2
Dec 24 '08 at 11:13
source share

In fact, you have to do both. When you say "database stub", this hints at a mockery in unit tests. And when you talk about “Installing the QA Database (Known Starting Point)”, this indicates integration tests in which you really hit the database. Unit tests go much earlier in the game, and the game taunts them. Mocking is much faster than actually getting into the database. Therefore, when you run a lot of unit tests, bullying will save a lot of time. Rhino Mocks is a great foundation that I personally used. But there are a few mocking frameworks, find one that works best for you.

At some point, you should put your complete database using integration tests, and the best way I have found for this is to have a script that completely creates and populates the database with a known dataset. Then, make sure that nothing touches your newly created database, other than integration tests, and open a trial version.

+2
Dec 24 '08 at 14:26
source share

We are moving towards using fake frameworks - they mock resources such as databases, configuration files, etc. Using these frameworks is a practical way to efficiently run your unit tests.

One of the structures we are working on is Rhino Mocks. You can read about it at the link below. It also has a good idea of ​​why you need such a framework.

http://weblogs.asp.net/stephenwalther/archive/2008/03/22/tdd-introduction-to-rhino-mocks.aspx

+1
Dec 24 '08 at 11:21
source share

I usually use two approaches.

Code that depends on the level of database abstraction works with IoC and is therefore easily tested with mocks / stubs. You have an IDataAccess or IRepository interface, and you check the interaction of your code with it.

The code that actually works with the database (say, a class that implements IDataAccess) is tested on its own, usually performs round trips to the database (insert-retrieve-update-retrieve-delete). Before running each test case, the database will be recreated or omitted to avoid crosstalk. This leads to tests requiring a few minutes to run instead of a few seconds, but in my opinion it is important to check the actual database that you will use in the production process. Using a replacement such as SQLite in memory is not a good choice because it is too different from, for example, SQL Server.

+1
Dec 25 '08 at 8:54
source share

here is a good screen shot in this section The meaning of small tests

+1
Dec 25 '08 at 10:33
source share

In my database testing practice, I used NUnit and before the entire test sequence was completed, the database was installed and populated with test data. Of course, this process was not very fast, but what prevents you from doing other work during testing.

0
Dec 24 '08 at 14:34
source share

Spring has test classes that are transactional. Collect test data, run the tests, throw them back. As if you were never there.

0
Dec 26 '08 at 13:49
source share

If you are trying to test a data access code, you will need a mocking framework . In the following link you can see the video tutorial database testing unit

0
Apr 24 '09 at 8:54
source share



All Articles