JUnit & Integration tests - Is it possible to run one ahead of any test that is run
I have extracted all my integration tests out of my multi-module setup and put them all into a separate project. These integration tests are based on spring and a use a real database. I am using dbmaintain which is a database versioning tool, it automatically tracks 开发者_如何学Gowhich SQL files need to be applied and keeps the database in a correct state.
What I would like is to be able to run the code that ensures the database is up to date before any test is run. So if you run all the tests (from Eclipse or Maven in my case) that it will first perform the db check once, or if you run a single test it will first perform the db check. No matter how many tests are run, it should always run the db check.
Right now I am thinking that I will use @BeforeClass in the base test class (all tests ultimately extend from this class) which will instantiate a singleton to do it's work. That singleton will control everything to make sure things only get run once.
I am hoping there is a cleaner way.
By default, the Maven runner for JUnit reserves the right to reorder tests. This is actually a Good Thing(tm), because you can tell the Maven JUnit plugin to run tests in parallel, which means you wouldn't know the order anyways. In addition, other tools (like TeamCity) can be set to run failing tests first.
I think your best bet would be to add your DB update code as part of the test suite setup (not part of your JUnit framework). Use the Exec Maven Plugin to call your DB code, binding it to the generate-test-resources phase. You'll want to make sure that when you run your tests, you actually call Maven to run the test.
JUnit does have the concept of an ExternalResource, which is a more explicit way of declaring the database dependency. It would be a few more lines of code than the base class, but depending on your perpective it may be more elegant.
Within Maven: (1) Add the dbmaintain plugin: http://source.mysema.com/display/maven/Maven+Plugins (2a) Call the appropriate goal (e.g. updateDatabase) explicitly before calling test (2b) Or, if you want the dependency to be executed during a specific phase, then maven supports this, too: http://maven.apache.org/plugins/maven-dependency-plugin/usage.html
Then, you can connect Eclipse to these Maven changes: How do I start Maven "compile" goal on save in Eclipse?
JUnit doesn't support test ordering. You will need to use TestNG for this. For example:
@Test(groups = "init")
public void initDatabase() { ... }
@Test(dependsOnGroups = "init")
public void test1() { ... }
@Test(dependsOnGroups = "init")
public void test2() { ... }
In this example, initDatabase() will be run first, and only if it succeeds will test1() and test2() be run. If initDatabase() fails, test1() and test2() will not run and they will be marked as "skipped" in the report.
Note also that you can add methods to any group at any time and the dependencies will keep working the way you expect them.
精彩评论