6

Here is some fake code under test:

public void saveItem() {
  try {
    databaseInterface.saveItemToDatabase(item);
  } catch (Exception e) {
      // deal with it 
      return;
  }
  itemList.Add(item);
}

When writing a unit test, if you were to not stub out that database call, test engineers would say that it is an integration test, not a unit test since it is calling a real database which makes the unit test slow, and a characteristic of a unit test is that it should be fast.

So, you stub out that database call, and test whether the item was saved to the list, ending up with a unit test.

You also create a unit test to test whether the saveItemToDatabase function was actually called, so in this new unit test you decide to mock the call and assert against it.

You are also tasked with unit testing your database interface, to make sure that items are actually being saved to the database, so you do so.

All your tests pass, so now you know that 1) items are being saved to the list 2) your saveItemToDatabase method is actually being called 3) your unit tests covering your database module show that the item is actually being saved to the database.

If I'm understanding integration test correctly, you would in an integration test, test all of these things, this time using a real database call in one test. So in one integration test your test might do the following:

  1. Create an item.
  2. Call saveItem() (an object method) which will save the item you just created.
  3. Query the database for the item using your database interface.
  4. Check that the item you created and the query result are equal.
  5. Check that the item you saved was added to the itemList.

It seems like the integration test is taking all the unit tests and rechecking what each unit test does, except this time you aren't stubbing or mocking anything out, so it makes it seem like integration tests are a bit redundant.

Am I misunderstanding what an integration test is? It sort of seems like a test that says, "yes, your production code is actually working when you don't stub or mock things out."

4
  • 1
    See here a clear definition: stackoverflow.com/questions/5357601/… Commented Aug 6, 2015 at 5:02
  • 2
    Keep in mind that all testing is to a degree redundant. That's part of why you do it: to phrase the same behavior in a different way that gives you more confidence.
    – Owen
    Commented Aug 6, 2015 at 7:50
  • An interesting related question: [How to use unit tests when using BDD]( programmers.stackexchange.com/questions/274562/…). It's about behavior driven development but BDD tests often straddle the line between acceptance and integration tests. It also addresses how unit tests fit into it. Commented Aug 6, 2015 at 13:13
  • While unit tests should be fast, the fundamental reason a test that calls the db is not a unit test is that you are testing more than the 'unit' (e.g method) under test; you are also testing the databaseInterface code, connection strings, any sprocs etc that get called etc. Commented Oct 8, 2018 at 15:06

2 Answers 2

10

It sort of seems like a test that says, "yes, your production code is actually working when you don't stub or mock things out."

That's exactly what it is.

Stubs and mocks isolate the infrastructure from your unit tests, which means that your units get tested, but not the infrastructure that you've stubbed out, nor the connections your units make with that infrastructure. It's the behavior of your units and the way that behavior interacts with the actual components that you've stubbed out that is being tested in an integration test.

Remember, stubs and mocks don't represent the actual behavior of a real system; they only simulate a small number of artificially-induced behaviors so that you can run your unit tests. An integration test not only provides a more realistic exercise of the system, but also a more comprehensive one.

2
  • 2
    Very insightful. But then a question rises, should there be unit tests if integration tests already cover use cases ? Since the units won't make the system functional without the infrastructure, it seems unit testing is not sufficient, while integration testing is. Is that correct ? Commented May 10, 2017 at 21:36
  • 2
    Test-driven development would be pretty difficult to do without unit tests. Even if you're not in the Test-First camp, unit tests can still be very useful for incrementally building up code and demonstrating that it works. If you're having to use a lot of mocks, it's a pretty good indication that your code isn't very well architected. Commented May 10, 2017 at 21:44
5

I think you have it backwards - the integration test is the "real" test, testing the system as a whole. But as it is a slow and often difficult to setup, we have unit tests as a stop-gap measure. They test bits in isolation which should give you an indicator that the code will probably work correctly when sent to the integration test.

You can write working systems without unit tests, you cannot do this without integration tests.

3
  • 2
    In sufficiently large systems with many states, logic and moving parts, both would be needed as integration tests can only cover "some representative test cases" due to impracticality of covering all possible combinations of execution paths (the phenomenon of combinatorial explosion) due to slowness. Unit tests try to cover the components underneath. (This comment is merely a response to your closing remark. It is not an expression of disagreement.)
    – rwong
    Commented Aug 6, 2015 at 8:41
  • 1
    @rwong except that you still have to find some way to test the combinations of execution paths - even though a unit works perfectly, it can still fail when combined with another unit. So even with hugely complex systems, you still need a full integration test suite. But unit tests help, its just that they're not the one and only form of test that should be used - which is really my point to the juniors who may get the wrong impression from various sources that unit testing is all they need.
    – gbjbaanb
    Commented Aug 7, 2015 at 12:24
  • Is it even worth it to test stuff that's not used anyway ? I'm talking about use cases which your functional tests don't cover since these paths simply don't exist in the application specifications. Which makes me wonder about the usefulness of unit testing if functional testing is enough to cover the application specifications. Commented May 10, 2017 at 21:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.