tags:

views:

220

answers:

5

I just discovered when creating some CRUD tests that you can't set data in one test and have it read in another test (data is set back to its initialization between each test).

All I'm trying to do is (C)reate an object with one test, and (R)ead it with the next. Does JUnit have a way to do this, or is it ideologically coded such that tests are not allowed to depend on each other?

A: 

If you are using JUnit 4.x, you can annotate the method that sets up the test data with @BeforeClass. This way, the test data is configured just one time, and it can be reused within your testcases without initializing the test data again and again.

limc
What exactly do I put in the BeforeClass method? I don't know the value from test 1 that needs to go into test 2 at the time I code the method. Either you misunderstood the question, or I'm misunderstanding the answer!
orbfish
A: 

Check out dbunit

Paul McKenzie
Not wild about adding an entirely new framework or rewriting all my tests this afternoon, but I'll keep it in mind. ;)
orbfish
+1  A: 

Well, for unit tests your aim should be test the smallest isolated piece of code,usually, method one by one. So testCreate() is a test case and testRead is anther. However, there is nothing that stops you from creating a testCreateAndRead() to test the two functions together. But then if the test fails, which code unit does the test fail at? You dont know. Those kind of tests are more like integration test, which should be treated differently.

If you really want to do it, you can create a static class variable to store the object created by testCreate(), then use it in testRead().

As I have no idea what version of Junit you talking about, I just pick up the ancient one Junit 3.8:

Utterly Urgly but works:

public class Test extends TestCase{

static String stuff;
public void testCreate(){
    stuff = "abc";

}

public void testRead(){
    assertEquals(stuff, "abc");
}

}

Jason Wang
It *is* an integration test - duh, CRUD means accessing the database.
orbfish
By the way, good idea about the static variable, if it works. I'll have to try it.
orbfish
That worked, thanks!
orbfish
+1  A: 

JUnit promotes independent tests. One option would be to put the two logical tests into one @Test method.

TestNG was partly created to allow these kinds of dependencies among tests. It enforces local declarations of test dependencies -- it runs tests in a valid order, and does not run tests that depend on a failed test. See http://testng.org/doc/documentation-main.html#dependent-methods for examples.

Andy Thomas-Cramer
So it *is* ideology! I was afraid of that. I did think, come to think of it, that there were some new annotations having to do with intertest dependency, but maybe I was reading about TestNG.
orbfish
It really is ideal for unit tests to be independent in both state and order. JUnit supports the ideal. TestNG supports both the ideal and pragmatic exceptions.Cedric Beust, the author of TestNG, discusses the issues in more detail in the sources below. He confirmed the intent of JUnit with Beck and Gamma, and found shortcomings with working around the JUnit approach with static members.* Beust's 2004 blog post http://beust.com/weblog/2004/02/08/junit-pain/* The first several pages of Beust's book "Next Generation Java Testing: TestNG and Advanced Concepts," Addison-Wesley, 2008.
Andy Thomas-Cramer
I agree with all that, for unit tests. But CRUD tests are database access and therefore not unit tests. It's a shame that JUnit, which is so flexible and pervasive, should be limited in any way that restricts it to unit tests only.
orbfish
Good point. In contrast, TestNG allows you to tag tests with a test category like "database" or "integration" via the 'groups' attribute; provides @BeforeGroup/@AfterGroup setup/teardown methods; and supports running or excluding-from-running a set of groups. More detail on Beust's slides 6-11 here: http://qconsf.com/sf2007/file?path=/QConSF2007/slides/public/CedricBeust_TestNG.pdf.
Andy Thomas-Cramer
A: 

How much processing time do these tests take? If not a lot, then why sweat it. Sure you will create some object unnecessarily, but how much does this cost you?

 @ Test
 void testCreateObject ( )
 {
      Object obj = unit . createObject ( ) ;
 }

 @ Test
 void testReadObject ( )
 {
      Object obj = null ;
      try
      {
            obj = unit . createObject ( ) ; // this duplicates tests aleady done
      }
      catch ( Exception cause )
      {
             assumeNoException ( cause ) ;
      }
      unit . readObject ( obj ) ;
 }
emory
Good point. It's more that I have to think up test data to ensure uniqueness in the 2 createObject()s, but this may be the way to go.
orbfish
I guess part of me resists writing the same "create" code twice. I'm over-DRY, methinks.
orbfish