views:

871

answers:

10

I am starting out with automated testing and I would like to test one of my data access methods. I am trying to test what the code does if the database returns no records.

Is this something that should be done in a unit test or an integration test?

Thanks

A: 

Most likely a unit test ... but there is a blurred line here. It really depends upon how much code is being executed - if it is contained to a library or class then its unit test, if it spans multiple components then it's more of an integration test.

Stephen Doyle
A: 

I believe that should be done in a unit test. You aren't testing that it can connect to the database, or that you can call your stored procedures... you are testing the behavior of your code.

I could be wrong, but that's what I think unless someone gives me a reason to think otherwise.

Max Schmeling
+5  A: 

Do your test and let other people spend time with taxonomy.

mouviciel
I think that the difference is important, because it helps you decide how to write it, who should write it, where it should live, when it should be run, and how failures should be handled. But that's no excuse for getting bogged down. Voted up.
Jay Bazuzi
Knowing what integration testing vs unit testing is can help you find good frameworks, tools or best practices for that specific task. This question was useful!
PRINCESS FLUFF
+10  A: 

If your test code connects to an actual database and relies on the presence of certain data (or lack of data) in order for the test to pass, it's an integration test.

I ususally prefer to test something like this by mocking out the component that the "data access method" used to get the actual data, whether that's a JDBC connection or web service proxy or whatever else. With a mock, you say "when this method is called, return this" or "make sure that this method is called N times", and then you tell the class under test to use the mock component rather than the real component. This then is a "unit test", because you are testing how the class under test behaves, in a closed system where you've declared exactly how the other components will behave. You've isolated the class under test completely and can be sure that your test results won't be volatile and dependent on the state of another component.

Not sure what language/technology you are working with, but in the Java world, you can use JMock, EasyMock, etc for this purpose.

matt b
Thinking of "unit testing" in sense of "closed system" is very helpful to differentiate it from "integration testing".
hurikhan77
+1  A: 

I believe that it is possible to test that as a unit test, without a real database. Instead of using a real interface to the database, replace it with a mock/stub/fake object (better visualized PDF is here).

If writing it as a unit test proves to be too hard, and you are not able to refactor the code that testing it would be easy, then you better write it as an integration test. It will run slower, so you might not be able to run all the integration tests after ever code change (unlike unit tests which you can run hundreds and thousands per second), but as long as they are run regularly (for example as part of continous integration), they produce some value.

Esko Luontola
+4  A: 

There are those (myself included) who have strict rules about what constitutes a unit test vs an integration test.

A test is not a unit test if:

  • It talks to the database
  • It communicates across the network
  • It touches the file system
  • It can’t run at the same time as any of your other unit tests
  • You have to do special things to your environment (such as editing config files) to run it

Which may be one way to make a distinction between what a unit test will be doing for you using mocking for example, rather than any of the real resource providers - filesystem, db etc.

An integration test can be viewed as a test of very coupling of systems/application layers, so the fundamentals are tested in the unit and the system interoperability is the focus of an integration test.

Its still a grey area though because one can often pinpoint certain exceptions to these sorts of rules.

j pimmel
+2  A: 

I think the important question is "What SHOULD I be doing?"

In this case I think you should be unit testing. Mock the code that talks to the DB and have it return a reliable result (no rows), this way your test checks what happens when there are no rows, and not what happens when the DB returns whatever is in the DB at the point you test.

Definitely unit test it!

[TestMethod]
public void ForgotMyPassword_SendsAnEmail_WhenValidUserIsPassed()
{
    var userRepository = MockRepository.GenerateStub<IUserRepository>();
    var notificationSender = MockRepository.GenerateStub<INotificationSender>();
    userRepository.Stub(x => x.GetUserByEmailAddressAndPassword("[email protected]", "secret")).Return(new User { Id = 5, Name = "Peter Morris" });

    new LoginController(userRepository, notificationSender).ResendPassword("[email protected]", "secret");

    notificationSender.AssertWasCalled(x => x.Send(null),
        options => options.Constraints(Text.StartsWith("Changed")));
}
Peter Morris
A: 

that is a unit test, by definition: you are testing a single isolated element of the code on a specific path

Steven A. Lowe
+4  A: 

My perspective is that you should categorize the test based on scope:

  • A unit test can be run standalone without any external dependencies (File IO, Network IO, Database, External Web Services).
  • An integration test can touch external systems.

If the test requires a real database to run then call it an integration test and keep it separate from the unit tests. This is important because if you mix integration and unit tests than you make your code less maintainable.

A mixed bag of tests mean that new developers may need a whole heap of external dependencies in order to run the test suite. Imagine that you want to make a change to a piece of code that is related to the database but doesn't actually require the database to function, you're going to be frustrated if you need a database just to run the tests associated with the project.

If the external dependency is difficult to mock out (for example, in DotNet, if you are using Rhino Mocks and the external classes don't have interfaces) then create a thin wrapper class that touches the external system. Then mock out that wrapper in the unit tests. You shouldn't need a database to run this simple test so don't require one!

Iain
+4  A: 

I think more time has been wasted arguing about what is a unit vs. what is an integration test than value has been added.

I don't care.

Let me put it a different way: If I were testing it, I'd see two ways to do it - fake out the database returning zero rows, or actually connect to a database that has no data for the select. I'd probably start testing with whatever was easiest to do and simplest to implement - if it ran fast enough for me to get meaningful feedback. Then I'd consider the other if I needed it to run faster or thought there would be some advantage.

For example, I'd probably start connecting to the actual test DB at my work. But if the software needed to work with many different databases - Oracle, PostGres, MySQL, SQL server and DB, or if the test DB at work was down for 'refreshes' a lot, I'd probably write the 'pure/unit' test that existed totally in isolation.

In my old age, I prefer to use the term 'developer-facing' vs. 'customer facing' more often, and do the kind of testing that makes more sense. I find using terms like "unit" extensively, then getting a definition-weenie about it leads to people doing things like mocking out the filesystem or mocking getters and setters - activity that I find unhelpful.

I believe this strongly; I've presented before google on it.

http://www.google.com/url?sa=t&amp;source=web&amp;oi=video_result&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DPHtEkkKXSiY&amp;ei=9-wKSobjEpKANvHT_MEB&amp;rct=j&amp;q=heusser+GTAC+2007&amp;usg=AFQjCNHOgFzsoVss50Qku1p011J4-UjhgQ

good luck! Let us know how it goes!

Matthew Heusser