Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I see all the examples that demonstrate unit testing code and mocking the calls to the DB since you are not suppose to touch the DB. But it seems to me having a set up tasks that uses the actually schema, loads the lookup tables and then populates it with data using the methods to be tested... This way it is more real world testing and all the stored procedures are tested as well.. But I never have seen any examples like this... Is there some reason I do not understand why using this technique is not as useful as it seems ?

EDIT1: Sorry.. I shouldn't have called it unit test.. yes. I will have unit tests as well that are for testing code.. But beyond that it seems like a good idea to bring up and tear down and DB and have code that modifies that DB and does assertions.. But I don't want this to be UI testing.. I just want to perform a lot of CRUD functions and a lot of assertions .. :My question is #1 does this make sense.. #2 how do I automate this all within visual studio ? How do I tell VS 2012 to run a SQL script before running the tests? is there some special API for this ?

share|improve this question
4  
A unit test that calls the database and stored procedures isn't a unit test. –  MichaelT May 7 '13 at 21:52
2  
@MichaelT: Mentally substitute the name you think should be there when you read the question. –  Robert Harvey May 7 '13 at 22:01
2  
A stored procedure by itself can be unit tested. The "real world" testing between your app and the actual database is integration testing. programmers.stackexchange.com/questions/101273/… –  JeffO May 7 '13 at 22:02
1  
Michael has a point, though... If you're looking for this in the unit tests, you're probably looking in the wrong place. –  Robert Harvey May 7 '13 at 22:02
3  
@RobertHarvey I read the question as the unit tests are written correctly (mocked calls to the database), but the poster is wondering why it isn't setting up a database and calling stored procedures and such. The lack of understanding (from the final sentence) is what the unit test is. –  MichaelT May 7 '13 at 22:05
show 1 more comment

6 Answers

Instead of just saying "Because it's a unit test", lets talk about why we might want to have a test that doesn't depend on a database.

Isolated Failures

We want a failing unit test to quickly identify where an issue is. The narrowest unit test failure already has two possible sources, both the unit under test and the test itself. Every dependency is another possible error source.

Assuming you do not have custom database data for every test, you run the risk that someone modifies the data for another test, but breaks yours. If you do have data for every test, then managing it all just became a pain. Schema change? Go modify every unit test.

Fast Failures

Unit tests should be fast. How fast? Fast enough that developers do not resist running them regularly, and do not waste time when doing so. Unit tests quickly lose a lot of value if people never run them because they spend 45 minutes setting up and tearing down the database 1000+ times.

Testing with the Database

That being said, our app does use a database. If we never test with the database, we don't really know if the app works. Many projects do this testing when testing the integrated whole, and usually get run less often than unit tests. For example, one of my projects involved several applications with unit tests that could be run in less than 30 seconds a piece, but the integrated system tests lasted 4+ hours on a compute grid.

share|improve this answer
    
Very good answer, I couldn't explain it better myself :) –  Jean-François Côté May 8 '13 at 12:24
add comment

Despite that many developers prefer the term "integrationtests" instead of "unittests" when external systems like databases are involved automated tests with databases are often painfull and fragile:

From Unit Testing with an In-Memory Database for a Spring/Hibernate Project

Testing DB code is often painful with any significant number of people. Often you 
either need every developer to have their own database, with it's own uniquely 
inconsistent data and ways of failing, or to use a shared database in which case 
people often manage to produce tests that don't work if more than one person runs 
the tests concurrently. Also testing on a "real" DB is slow and subject to failure 
for reasons not related to your code. 

With fragile i mean "does the test fail because there is a logical error in the code or is it because someone deleted a datarow that is required by the test".

In order for database related tests to work you need to have a predefined set of databasecontent wich must be maintained. We have projects where there is a automated-testing-ony database where the developpers are not allowed to modify any data.

The other alternative is that the automated test generates the required test-data itself and works with an in-memory database.

share|improve this answer
    
you can write data to the DB in the unit test - transactions are great for this as you simply rollback at the end of the test call. You don't need anything fancy like an in-memory DB or a special DB with special data. –  gbjbaanb May 8 '13 at 12:17
    
> "Also testing on a "real" DB is slow and subject to failure for reasons not related to your code." But those are exactly those reallife scenarios where the app fails. Lots of people working with your program all on the same database. It's often those "not related to your code" things you need to work around because they work in the lab but fail in the field. –  Pieter B May 8 '13 at 13:08
add comment

It's because a unit test shouldn't have any dependencies. It must be self contained. Unit tests exists to test a "unit" of logic in your code by treating it as a black box. The specific source of data (database or other) should have no impact on the logic.

Anything else, even if called via a unit testing framework isn't classed as a unit test. It would be a different type of test such as a functional test.

It's worth looking up some of Kent Beck 's material on TDD.

share|improve this answer
add comment

MSTest?

The other answers say why you need to test in isolation, but you then test the DB stored procedures as well - call them with a certain input to a table filled with pre-defined data, and see what result is returned. Each test sets up data, calls the test code, then rollsback so the DB is back to its original state.

This is easy, use it in conjunction with your client-side tests. (its just a shame few people know enough to realise that unit testing applies to SQL as well as C# code, if only they would split the sql code into stored procedures they'd find DB testing was as easy. Few people write proper DB unit tests, which is surprising given how important the DB aspect is to most programs).

Now there is a separate issue with integration testing, and for that you'll need to set up a DB with sample data and then call your client (using Selenium or similar) so that you exercise the whole thing end-to-end. This isn't unit testing per-se. It is still very useful, and you really should be doing this as well - unit tests only verify the tiny detail of little bits of code and ignore the 'bigger picture' of how they work together. Integration tests will verify that your entire app works when all those little units are plugged together.

share|improve this answer
add comment

The definition of unit test is a test that tests single unit of behavior in isolation. A test that tests integration with the database is testing neither a single unit nor in isolation, therefore it is by definition not a unit test.

Asking why there are no unit tests that integrate with the database is like asking why there are no odd numbers divisible by two: it's simply because of the definition of the word "odd number".

share|improve this answer
    
While this is correct, I think the key thrust of the question was "why aren't there tests that do this", the use of the phrase "unit test" in the question is a distraction from what is really being asked. –  Carson63000 May 7 '13 at 22:30
add comment

Database testing is not done in Unit test but in Integrated test.

share|improve this answer
1  
This is correct, but you should add some details as to why you wouldn't create and connect to a DB in a unit test and what makes doing so an integration test. –  StuperUser May 8 '13 at 13:41
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.