Junit/Mockito: choosing to run test with mocks or integration tests
I'm learning Mockito. Before starting to use mock objects I had some Unit tests that were more like integration tests, so I'd have a test class with a 开发者_运维知识库setUpBeforeClass() like this:
@BeforeClass
public static void setUpBeforeClass() throws Exception {
instance = new UserDataAccess();
instance.setDb(new MyDb());
}
Now with the mock Object is a lot similar, but the setup is slightly more complicated:
@BeforeClass
public static void setupBeforeClass throws Exception {
instance = new UserDataAccess();
MyDb myDb = mock(MyDb.class);
when(...).thenReturn(...);
...
instance.setDb(myDb);
}
Also I've a test suite that used to load the DB in a well known state before running the tests, and this is done with the first test class called by the suite.
What I'm thinking is that I should not throw away the integration tests, so I was considering to split the test suite into a UnitTestSuite and a IntegrationTestSuite. In fact the mock tests, are not testing everything, for instance they don't test if queries are correct.
Also, the only difference between those two suites, will be the initial DB reset and the setUpBeforeClass() code. It would be a waste to copy and change all the test classes just to change a method. The initial DB reset is easy to skip, I just not include the db reset test class in the Unit test suite.
To split unit and integration tests what do you suggest? Extending all the original classes to override the static method and then including the right class in the suite?
Or other approaches? How are you doing it, or what would you do?
Always remember that the idea behind unit tests (using mocks) is to poke and prode all the dark corners of a single class. They are about making sure that the class behaves as expected for all the sorts of input you can think of. Thats why we use mocks for doing this, because we can program those mocks to do all sorts of things that might be difficult to reproduce if the class was hooked up to the rest of the application.
Integration on the other hand, has a different emphasis. It's about making sure that all your classes work together to produce the desired result. So keep that in mind when coding them. It's the big picture that you are after. You don't need to worry about obsure edge cases of individual classes because that's the job of your mocked unit tests. But things like database state are exactly why integration tests are important.
I also agree with @stivlo about using products like HSQL for in memory database work. They can both speed up integration testing and help to ensure a known starting point for a test.
I would suggest keeping your unit tests and integration tests in seperate directories or at least seperate packages named to match. Simple because it helps you to remember what you are dealing with.
Also watch out for test creep. Ie. Unit tests that are instantiating a lot of application classes and really should be moved into integration tests, and integration tests that are doing lots of detailed variation style tests on a class - candidates for a unit test. Particularly with the last you can prune a lot of time off a build if there are integration tests which should not exist.
Finally like any code, test code needs a little love and attention from time to time. So keep an eye out for refactoring opportunities. That being said, I've also seen test code that has become difficult to work with because it's too generalised and over engineered. Remember test code is not production code, so in most cases clarity is far more important than engineering. It's a balance that you will get through experience.
I'd suggest to use in-memory database for integration tests, not a mock object.
For unit test I assume you're using database as stub to provide some data into the tests and as a mock when your test calls something like saveMyDomainObject()
. In the first case you can mock only what you actually need for a particular test, not the whole database setup. For the second case you should use Mockito's validate
to check that the expected behavior is correct.
精彩评论