So, I'm trying to stub a database connector in order to write tests for it. The problem is that the database connector is a pretty thin layer, and the queries to it are somewhat open-ended. I want my code to be able to ask for a variable from the database, and the connector should be OK with this. The signature for this call looks something like this:
dim = getDimension(self,dimensionName,otherIndentifyingInformation)
(This is all in MATLAB - hopefully the answer is language-agnostic, or at least not infeasible in MATLAB.)
When I use it in my code, dimensionName
is one of a few things that are stored in the database. If the code calls it, and it doesn't exist, that's fine. The problem here is that I want to test some code that makes two calls to getDimension
, something like:
alt = conn.getDimension('alt',otherID);
str = conn.getDimension('str',otherID);
For (hopefully) obvious reasons, alt
and str
are not guaranteed to be the same. In fact, they're typically not.
So, my question. If I want to stub getDimension to return good test values, how can I do this? Creating getDimensionAlt
seems kludgy, since the number of things that could come out of the database is somewhat unbounded, and that would be a pain to maintain. Is there a better way than putting logic in my stub objects? That just seems like the wrong way to go about this...
EDIT: Setting up a testDB was suggested. Wouldn't I have to set up a testDB for each test case, then? And in each test, I'd have to create a DB connection, return it as a stub, run the test, and then clean up the DB connection. This seems like it would be a lot of overhead for each test, especially when it isn't even the system I'm testing.
I suppose it's possible to set up a testDB, and fill it with the appropriate values each time. Is that good practice?
EDIT 2: Perhaps my question is unclear. I have a small piece of code I'm trying to test. It's not a lot more complicated than those two lines above, and I'd like to test it cleanly. The problem is that stubbing the getDimension
call is dependent on the arguments. I don't need to reuse this stub with other tests.
I think the answer might be "It's OK to have simple logic in your stubs." This is all confounded by the fact that there's no anonymous classes or stubbing framework in MATLAB, so that's hard, but I want to make sure what I'm doing is conceptually clear before I go off and write a stubbing framework in MATLAB.
-
Could you set up a a test database with known values and then perform a known set of queries against it (with known expected return values)?
TR : I clarified my post - I have some misgivings about that. Could you expand a little on this idea?Mr Fooz : I guess I don't see why you want to stub it when it should be easy to write a real test against a real (tiny) database with real (known) values. Populate the DB with everything you need for the tests and test against it. Presumably this would be a small DB. -
I think setting up a testdb is a good idea if you're doing automated integration tests or acceptance tests. This usually calls for tests where you test the whole stack (UI, application, database, services etc.) at once.
Unit testing is quite different, they are used during development and not during testing, therefore they should be quicker to run, quicker to change and quicker to write. Its usually a good idea to have unit tests only depend on the small piece of code they're testing. This makes them less brittle, easier to understand and makes developers more willing to run them often.
Using stubs in unit tests is a good idea. The problem you seem to run in to is that if you want to reuse stubs for many tests their behaviour can get very complex, in the worst case you're rebuilding the thing they are supposed to stand in for. This can also happen if you are testing too much at one time.
The solution to this is to have more smaller stubs that only implement the behaviour for one or a few tests and have your tests only test a single behaviour. Tests that test lots of behaviour at once are useful too but they're not unit tests, you should move them to your integration test suite (and can run on a real database). I'm not sure about matlab but in many languages you have mocking frameworks you can use to handle creating stubs and setting up behaviour for you.
-
My answer on a similar question http://stackoverflow.com/questions/595926/creating-mock-data-for-unit-testing/595965#595965:
You can have Builder class(es) that helps you building the instances you need / in this case ones you would use related to the repository. Have the Builder use appropiate defaults, and on your tests you can overwride what you need. This helps you avoid needing to put have every single case of "data" mixed up for all the different tests (which introduces problems, because usually there are cases that aren't compatible for different tests).
Update 1:Take a look at www.markhneedham.com/blog/2009/01/21/c-builder-pattern-still-useful-for-test-data
Also check this answer, on the overall unit test relation to external systems: http://stackoverflow.com/questions/589603/how-can-i-improve-my-junit-tests/589620#589620
Note there is an alternative using in-memory databases like dbunit. I prefer the builder, for the reasons mentioned in the later link.
0 comments:
Post a Comment