I currently use using (TransactionScope scope = new TransactionScope()) for
c# testing database insertion so that it doesn't actually save into database for unit testing. But for system testing which I am currently testing on different server to test the status code for different scenarios. Each time I run the test, it is actually saving data into database and next time I ran the test it is failing as it is duplicate record. I tried to use transaction scope , but doesn't seem to work. Please help.
Related
I am writing unit tests in .NET that are heavily dependent on database. Unit test modify the data in the database and I want to revert the database to the initial state. I am planning to follow the approach listed below for reverting the database to pre unit-test state.
Approach: I want to create a database snapshot before running each unit test and rollback database to that snapshot after it is finished.
The problem: many users can simultaneously run the test cases. This can result in different snapshots (inconsistent). How can I handle the concurrency problem? I do not want to pollute the database in any way for the sake of running test cases.
I am using SQL Server 2012 and .NET (C#) for accessing the database.
When running c# integration tests, I'm trying to recreate my table in a transaction scope for each test, though I'm getting the following error:
DROP DATABASE statement cannot be used inside a user transaction.
What does it mean? How do I handle it?
I am still having a issue getting over a small issue when it comes to TDD.
I need a method that will get a certain record set of filtered data from the data layer (linq2SQL). Please note that i am using the linq generated classes from that are generated from the DBML. Now the problem is that i want to write a test for this.
do i:
a) first insert the records in the test and then execute the method and test the results
b) use data that might be in the database. Not to keen on this logic cause it could cause things to break.
c) what ever you suggest?
You should choose option a).
A unit test should be repeatable and has to be fully under your control. So for the test to be meaningful it is absolutely necessary that the test itself prepares the data for its execution - only this way you can rely on the test outcome.
Use a testdatabase and clean it each time you run the tests. Or you might try to create a mock object.
When I run tests using a database, I usually use an in-memory SQLite database.
Using an in memory db generally makes the tests quicker.
Also it is easy to maintain, because the database is "gone" after you close the connection to it.
In the test setup, I set up the db connection and I create the database schema.
In the test, I insert the data needed by the test. (your option a))
In the test teardown, I close the connection to the db.
I used this approach successfully for my NHibernate applications (howto 1 | howto 2 + nice summary), but I'm not that familiar with Linq2SQL.
Some pointers on running SQLite and Linq2SQL are on SO (link 1 | link 2).
Some people argue that a test using a database isn't a unit test. Regardless, I belief that there are situations where you want automated testing using a database:
You can have an architecture / design, where the database is hard to mock out, for instance when using an ActiveRecord pattern, or when you're using Linq2SQL (although there is an interesting solution in one of the comments to Peter's answer)
You want to run integration tests, with the complete system of application and database
What I have done in the past:
Start a transaction
Delete all data from all the tables in the database
Setup the reference data all your tests need
Setup the test data you need in database tables
Run your test
Abort the transaction
This works well provided your database does not have much data in it, otherwise it is slow. So you will wish to use a test database. If you have a test database that is well controlled, you could just run the test in the transaction without the need to delete all data first.
Try to design your system, so you get mock the data access layer for most of your tests. It is valid (and often useful) to unit test database code, however the unit tests for your other code should not need to touch the database.
You should consider if you would get more benefits from “end to end” system tests, with unit tests only for your “logic” code. This depend to an large extent on other factors within the project.
I am trying to find out in Visual Studio 2010 Unit Testing how to keep a transaction of the data I have either added, updated, or deleted during my tests so on my TestCleanup I can rollback their values.
What search terms should I be using to find more about this?
Cheers
Paul
Why do you need to rollback changes? Are your unit tests updating live data? If unit tests are written properly, you shouldn't have to clean up after what your tests changed because the data they're changing should be isolated to your test.
Edit:
It sounds like you've set up a data set for testing and want to make sure that data set is restored back to its original state. I prefer the practice of setting up the test data as part of the test, but I understand that can get difficult for complex tests.
If this in an ADO.NET data source, you could start a transaction then roll back that transaction at the end of your test. For example:
using (var transaction = db.BeginTransaction())
{
// Do tests here
}
// The transaction is rolled back when disposed
Edit 2:
A third option, if you don't have transaction support, is to have a backup of your test data in a place where it won't get modified, then at the end of the test, restore that backup.
For unit testing you should probably try using mocks instead of accessing a test database. Unit tests should generally be completly self-contained (and not rely on external sources e.g., databases).
If you are actually testing calls to the database then this is probably an integration test in which case you could:
Create test data in setup
Run code
Assert test passes
Remove test data inserted in step one
I am trying to do some automated web testing of my ASP.NET application. I was hoping to use the AutoRollback attribute from Xunit.net extensions to undo any database changes that were made during the test. AutoRollback uses TransactionScope to start a transaction before the test and roll it back afterwards.
When I try to hit my web application during a transaction, it always times out. It seems like this should work, any ideas? Here is my test:
[Fact]
[AutoRollback]
public void Entity_should_be_in_list()
{
Entity e = new Entity
{
Name = "Test",
};
dataContext.Entities.InsertOnSubmit(e);
dataContext.SubmitChanges();
selenium.Open("http://localhost/MyApp");
Assert.True(selenium.IsTextPresent("Test"));
}
Your ASP.NET application has a separate database context and it has no idea that you want it to join transaction started by Xunit.net. Apparently, the database locks some resources when transaction starts; web application waits patiently for some time and eventually gives up.
I think your best bet is to start from empty database and use SQL script to create schema and populate lookup tables (your database is under source control, right?). Another approach is to backup database before running the tests and then restore it once they finish.