Reputation: 1258
Short Question
Is there something you can run sql commands that have JOINS and WHEREs that is not a DB
Long Question
I am putting in unit tests for a brown field win forms app. I have complete freedom of choice on what kinda unit test framework I have
The problem I have is there is masses of SQL string statement in the code. Think something like this
SELECT *
FROM Sale
INNER JOIN SaleItem ON Sale.ID = SaleItem.SaleID
WHERE ID = 5
It is parameterized, and has IF statements to build up the where, so it might be where CustomerId = 5 or DispatchDate was in last year. The query is a lot bigger that this, and I kinda want to check that all the joins work and all the possible wheres work. Do think this might be me looking at the detail to much
I dont want to have to manage a database of data, which if the data changes it will break tests, and I'm scared that will root and people will just kill of the tests.
I want to run this sql against some object or a thing, that is NOT a DB and get a item. It has to be smart enough to actually filter So it the Sale object was like the following table, it would only return the one with the ID 5.
ID DateDispatched CustomerID
1 1/1/1 5
2 2/2/2 6
5 3/3/3 7
I have thought of running sql command on datasets and XML, and relised that wont work. I guess LINQ has spoiled me over that last few years cus I cant work out how to do this. And im afraid there is so much logic building up massive SQL statement, I have to put some tests on them.
Would be more than willing to hear about other options like moving the SQL to stored procedure in the DB, if you can recommend a good unit testing framework.
Now I don't like SQL being built in the app and would love to change it to entity framework, but its a 10 year old application and that's just not a option.
Okay some quick edits The database is on SQL Server 2012, so stored procedures are a option, as in some places they use stored procedures.
Upvotes: 1
Views: 3303
Reputation: 1258
Okay I took the old adage of if you cant change your employer, change your employer.
I think tsqlt http://tsqlt.org/ would of been the best fit for this exact problem.
As Entity framework would not be allowed and they had so many dependency tables. Which would let me mock tables move all logic to stored procedures and mock the tables. Kinda mix of Yogi and JWG answer.
Upvotes: 0
Reputation: 150
Here is an option that we use for our unit testing with MS test
Use the TransactionScope from the System.Transactions namespace in your TestInitialize method Create an instance of the transaction and in the TestCleanup method dispose of it. You can do the insert into the db in the test initialize method or in the individual test methods
[TestCleanup]
public void testClean()
{
_Trans.Dispose();
}
[TestInitialize]
public void testInit()
{
_Trans = new TransactionScope();
}
[TestMethod]
public void TestQuery()
{
// arrange
//' insert data
// act
Obj Target = Obj.New();
// Assert
Assert.AreEqual("someValue",Obj.SomeProperty);
}
Upvotes: 0
Reputation: 5837
A SQLite database is designed for exactly this kind of requirement.
The database is a simple file. The database driver reads from and writes to this file. You can run all the SQL queries and so on that you are used to against the database. (However, you might have problems if your SQL uses language or syntax specific to SQL Server.)
It is true that you have to manage a 'database' full of data. But you should be able to:
Thanks for the question - I have been thinking a lot about testable database code recently, and I hadn't figured out a solution to this type of problem until your question made me realize I already knew it.
In my opinion, there are three approaches to make this kind of testing as painless as possible in the long-run:
Upvotes: 0
Reputation: 9749
Let me try to understand your problem.
You have got an winform application and you are writing unit tests for this. But if you run the the test, you afraid it will going to hit the DB and spoil the data. So you want some mechanism which allows to run your unit tests but will not hit the actual database. Correct?
If I got your problem right, I suggest to separate out your db interaction logic and make it interface driven. Then you can create mock objects, wherein you define the expectation of your db interaction interfaces. So for example, if some GetSales() method is called, what should be returned from this method? and so on. Sharing some links on details about unit testing and mocking.
https://msdn.microsoft.com/en-us/library/ff650441.aspx
http://www.developerhandbook.com/unit-testing/writing-unit-tests-with-nunit-and-moq/
Testing a MVC Controller fails with NULL reference exception
Upvotes: 1