8

My classes are following this structure

  • Service Tier (creates and maps InputDTO to DB Data)
  • DAO Tier (actually executes DB calls)

When I write service tier JUnit tests, the DAO tier is called, and this expects an actual DB connection and getting data from the DB.

Should I be mocking the DAO tier completely from the service tier, or should I be mocking the DB connection and data received from the DB?


Secondly, the app expects certain data from a cache.

For JUnit run time, there is no cache, so how should this be handled? The service tier method includes looking up the cache to get the details.

3 Answers 3

9

I'm going to talk about Test Doubles, if you haven't run across this term then you'll probably wan to read Martin Fowler's article link first.

  • For the Database testing - If you are following a pure Unit testing approach then you would use a Stub or a Mock type of Test Double to mock out the DB connection and its responses. If you are using a Mock then I would recommend using Mockito, JMock or your other favourite mocking tool. However, this is quite laborious when it comes to testing a large third party resource such as a database.

  • For the Database testing - If you are following a slightly looser definition of unit testing, then you could use a Fake Test Double. In your particular case, this would be an in memory database such as HSQL. This is a very popular way of 'unit' testing your database layer. Some will argue that this is not unit testing, and that it is integration testing instead. I think that's actually OK - the fact of the matter is, you have some tests excising your code :-)

  • For the cache testing - A Stub style of Test Double is likely to be your friend here - depending on how complex the cache API is.

HTH!

4
  • 3
    Lovely answer, our idea is the pure unit testing approach - trying not to create large integration tests but smaller unit tests. I was not aware of the term Test Doubles, thanks Nov 10, 2011 at 10:24
  • 2
    +1 always favour the smallest, simplest way of exercising the specific code you are working with. As the system grows introduce integration/functional/system tests to act as fast fail indicators.
    – Gary
    Nov 10, 2011 at 11:27
  • 1
    +1 For mentioning Mockito. It is by far the most intuitive mocking framework I have ever used in any language, and it even has nifty features that reduce the pain of retroactively forcing in unit tests to legacy code that was never originally designed with unit tests in mind. The Mockito Spy object is incredibly useful for this.
    – maple_shaft
    Nov 10, 2011 at 12:19
  • The term "unit test" is nowadays most commonly used to describe technical characteristics of a tests: a unit test is a test that runs fast and without prerequisites. The term "integration test", when used properly, describes the purpose of the test: to test the integration of parts. So a "unit test" can easily be an "integration test" if it tests some integration and runs fast.
    – oberlies
    Jul 10, 2015 at 9:00
2

In the abstract the answer is quite simple.

You have three layers.

[The test case] -> [The behaviour under test] -> [The collaborators used by that behaviour]

The third layer is what should be mocked. For example:

  1. the PokemonCaptureServiceTest;
  2. tests PokemonCaptureService;
  3. which uses Pokeball

In this example it turns out that Pokeball is third party logic. It requires all sorts of plumbing like database connections and property files etc. You trust your third party has tested it appropriately, so you'd like to omit it from your testing of PokemonCaptureService. Hence it should be mocked.

However, in another time and place, the collaborator Pokeball is a simple class that introduces very little complexity into the test case and can be included in the test easily. In this case you may decide to include a real instance of Pokeball in the PokemonCaptureService instance being tested.

There is no hard and fast rule. It is up to you to design your tests in the way that seems best to you. Your objective is to create correct and maintainable tests as quickly as possible. Experience is key here. Write more tests & you will very soon gain a good intuition for it.

0

It's hard to tell what exactly you want to test because judging from the question you're all over the place. Thus it is hard to give you any practical example on how to proceed other than lead you to articles on how to mock stuff. So you need to be more specific and split things up a bit:

  • Do you want to test so that the cache works properly?

  • Do you want to test some DB call in particular?

  • Do you want to test the app so that it is using the cache correctly?

Once you decide exactly what the unit is that you want to test, then selecting what to mock becomes easy: in a pure unit test, everything but the "unit under test" should be mocked. The rationale behind this is that you can be sure from your set up expectations on the mocks that the tested unit works as it should.

Other than that, you might want to write some tests in JUnit that are integration tests, i.e. use less mocks. Even if they're used as sanity checks to see if the software design is correct you should be aware that they will be brittle and won't always give any indicator on what exactly is wrong with your app or system.

Your Answer

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

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