Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing rules

My question may appear really stupid for some of you but i have to ask.. Sorry..

I don't really understand principles of unit testing.. How can you test classes of your business classes or Data access layer without modify your database? I explain, i have a functionality who update a field in a database.. Nothing so amazing.. The Business layer class is instantiated and the method BLL.Update() makes some controls and finally instantiate a DAL class who launch a stored procedure in the database with the correct parameters.

Its works but my question is..

To do unit tests who test the DALayer class i have to impact the database in the tests! To test for example if the value 5 is well passed to the DataBase i have to do that and database's field will be 5 after the test!

So i know normally the system is not impacted by tests so i don't understand how you can do tests without without execute methods..

Tx for answers and excuse my poor English..

like image 948
bAN Avatar asked Aug 16 '10 14:08

bAN


4 Answers

If you are not resorting to mocking and using actual DB in testing then it will be integration testing in layman terms and it's not a unit test anymore. I worked on a project where a dedicated sql .mdf was in source control that was attached to database server using NUnit in [Setup] part of [SetupFixture], similary detached in [TearDown]. This was done everytime NUnit test were performed and could be very time consuming depending upon the SQL code you have as well as size of data can make worse.

Now the catch is the maintenance overhead, you may change the DB scehma during you sprint cycle and at relaease, the change DB script has to be run on all databases used in your development and testing including the one used for integration testing as mentioned above. Not just that, new test data (as someone mentioned above) has to be popoulated for new tables/columns created and likewise, the exisitng data may need to be cleansed as well owing to requirements changes or bug fixes.

This seems to be a task in itself and someone competent in team can take the ownership or if time permits you can integrate the execution of change scripts as part of Continuous Integration if you already implemented one. Still the adding and cleansing the test data need to be taken care of manually.

like image 42
Kay Khan Avatar answered Oct 12 '22 16:10

Kay Khan


I will divide your question into several sub questions because it is hard to answer them together.

Unit testing x Integration testing

When you write unit test you are testing simple unit. That means you are testing single execution path in tested method. You need to avoid testing its dependencies like mentioned database. You usually write simple unit test for each execution path so that you have good code coverage by your tests.

When you write integration test you are testing all layers to see if integration and configuration works. You usually don't write integration test for each execution path because there is to many combination accross all layers.

Testing business classes - unit testing

You need to test your business classes without dependency to DAL and DB. To do that you have to design your BL class so that those dependencies are injected from outside. First you need to define abstract class or interface for DAL and pass that DAL interface as parameter to constructor (another way is to expose setable property on BL class). When you test your BL class you will use another implementation of DAL interface which is not dependent on DB. There are well known test patterns Mock, Stub and Fake which defines how to create and use those dummy implementations. Mocking is also supported by many testing frameworks.

Testing data access layer - integration testing

You need to test your DAL against real DB. You will prepare testing DB with test set of data and you will write your tests to work with that data. Each test will run in its own transaction which will be rolled back at the end so it will not modify initial data set.

Best regards, Ladislav

like image 52
Ladislav Mrnka Avatar answered Oct 12 '22 16:10

Ladislav Mrnka


For the scenario you describe in terms of db interaction, mocking is useful. If you have a chance, take a look at Rhino Mocks

like image 38
Ta01 Avatar answered Oct 12 '22 18:10

Ta01


You use Inversion of Control together with a mocking framework, e.g. Rhino Mocks as someone already mentioned

like image 25
Grzenio Avatar answered Oct 12 '22 18:10

Grzenio