views:

278

answers:

5

Hello all,

I was wondering if anyone here has experience in unit testing LOB applications (typically CRUD).

I have dabbled in the built-in unit testing tools in Visual Studio, but I have found it difficult to run tests that hit a database. Since the data changes, and combined with the fact that I have little idea what I'm doing, it seems very difficult to produce expected results and assert against them. Also I've even heard that you shouldn't run unit tests against databases... but how does everyone else out there perform unit tests on CRUD LOB software?

I hear so much about TDD and continuous integration with testing, but it seems like if i can't even create unit tests to begin with, I can't really use those methodologies. It makes since that a product like Notepad would be an easy one to create unit tests for... you have a certain amount of features and those features should always produce the same result. But with LOB applications, you've got things like Sales Orders that could be created or deleted or modified in your testing environment.

Any insight would be appreciated!

+1  A: 

Typically with CRUD you are going to need to either Mock or use an IOC Container for your data access layer so you aren't always hitting the database and "changeable data".

With unit tests, you always expect the same values, so having it hooked up to a database is typically going to cause problems.

Check out RhinoMocks or Inversion Of Control Containers.

Tom Anderson
moq is also cool, http://code.google.com/p/moq/
Chance
+1  A: 

The post below speaks to this very same topic

http://stackoverflow.com/questions/38598/how-do-you-unit-test-business-applications

Toran Billups
+1  A: 

I create a baseline database and use dbUnit to export it to a set of XML files. The first pass of the test is wipe out and populate the test database with the baseline. After that, you should be able to assert the unit tests against the expected values.

Otávio Décio
+1  A: 

Automated Testing is a broad category, which contains two smaller categories: Unit Testing and Integration Testing.

Unit Testing is the practice of identifying the smallest units of your program, and writing procedures testing them in isolation from each other. When the smallest units of your program are coupled together tightly, it may be hard to test them in isolation from each other. In that case, there are techniques and tools to help you (mocking and mocking frameworks). In order to effectively do unit testing, your codebase needs to be written in a particular way, a way which supports unit testing - the smallest units of your program must not be coupled together. Most programs are not built with this principle in mind, and so they are difficult to unit test. Unit test where you can, and keep that principle in mind for any new code you write, so that you can always unit test your new code.

Integration Testing is the practice of identifying features that are large units of your program integrating many smaller units, and writing procedures testing them in isolation from other large units of your program. For example, a procedure testing that your persistence layer correctly saves objects to persistent storage and correctly retrieves objects from persistent storage is an integration test, because it tests both your persistence layer as well as the TCP/IP pipeline, the database configuration, the database schema, the data already in the database, and the interaction between data already in the database and what your code is doing. Definitely do integration testing, in addition to unit testing.

Also, create a separate database purely for the purpose of automated integration tests. Try to avoid running automated integration tests on a production or a development database, because you will just run into problems.

Justice
very nice read, thanks!
Bjørn
A: 

I stumbled upon the same problem, you don't have that many options...

  • rollback after every test (using xtUnit for NUnit or the MbUnit rollback attribute). this works fine for typical unit tests of CRUD operations.
  • use a backup restore strategy before after a test. This will make unit test execution long. This is however supported by MbUnit (2.X the attributes are not present in the 3.x trunk)
  • create/drop a db using sql scripts.

The biggest advantage with the last 2 options is that you can use them while executing so called integration tests (like when automating an UI where you need to support database changes on some other tier (physical server)).

I use the last one in combination with Watin for web app's. For WPF and Win32 take a look at White, it looks promising.

Cohen