0

I'm new to unit testing and I'm trying to test tree like structure like so:

  A
  |
  B
 / \
C   D

I have written unit tests for C and D using JUnit4, and now I want to test B. Is there a smart way of doing this which doesn't require me to replicate all the code that sets up C and D?

I basically want to first run the tests for C and D, then with those data structures loaded, run the test for B, and then run the test for A, all in one go without any tearing down.

How would I go about for setting this up in JUnit4?

Ehsan Kia
  • 1,475
  • 18
  • 26

4 Answers4

0

C and D extends B so you can access B's methods using C/D's object. As B extends A, you can access A's methods also with C/D's objects. (Unless they are overridden)

Crickcoder
  • 2,135
  • 4
  • 22
  • 36
  • Sorry if I wasn't clear, there's no inheritance happening. These are all completely different objects, B just holds C and D in its fields. These are just different data structures. – Ehsan Kia Sep 27 '13 at 07:28
  • Then you can do vice-versa. An object of B would have C/D objects and can be tested in the same test run – Crickcoder Sep 27 '13 at 07:32
  • That's my question, how would I set it up so that it's tested in the same run, while C and D are still loaded. – Ehsan Kia Sep 27 '13 at 07:33
  • for that you need to paste the code of B... may be in a different question – Crickcoder Sep 27 '13 at 07:35
  • B just has fields private C c; and private D d; and these two objects are pretty painful to create, but that's done in their respective tests. – Ehsan Kia Sep 27 '13 at 07:38
  • then B b = new B(); and b.getc(); will give you object of C.. right? – Crickcoder Sep 27 '13 at 07:39
  • Sure, but B takes object C and D in the constructor, it's null by default. So to create B, I need C and D to be created first. – Ehsan Kia Sep 27 '13 at 07:41
  • Your test for B should not depend on C and D. Keep your tests for C and D as they are. Then write a test for B replacing the instances of C and D with mocks. This way you can be sure that you're only testing the functionality of B and you save yourself from repeatedly setting up test instances of C and D. If B already takes C and D in the constructor basically all is set up for already :) – Sven Amann Sep 27 '13 at 07:42
  • @salsolatragus.. I don't think that solves Ehsan's problem. He wants to reuse the code for test runs – Crickcoder Sep 27 '13 at 07:46
  • @G V: Sometimes the problems we see are not the problems we have ;) Anyways, @Ehsan Kia: you can use JUnit's Test Suites functionality to define a setup/teardown on a higher level and then run all tests of the suite "in between". – Sven Amann Sep 27 '13 at 07:59
0

There is no guarantee regarding the order in which tests get executed in Junit. This is intentional, since separate tests should not depend on one another.

How do I use a test fixture?

(...) The ordering of test-method invocations is not guaranteed, so testOneItemCollection() might be executed before testEmptyCollection(). (...)

Maybe you can explain a little more why you want to achieve this specific behavior? I'm not sure from what you write, why you need this single setup and fixed test order.

EDIT ---

Okay, from the discussions I now see that I missunderstood your problem. I think the way to go for you is either

  • Use JUnit Test Suites to setup all your objects and the run the separate test classes as part of the suite or
  • Decouple your tests by using mocks for D and C in the test for B so you only need to set C up in the test for C and D in the test for D.
Community
  • 1
  • 1
Sven Amann
  • 565
  • 2
  • 12
  • I'm not talking about test methods, but rather about the whole test class. The test class for C creates a C object and tests it. Test class for B needs the C object, so it needs to create it, but the setUp for C already does that. Do I need to copy the setUp of C and the setUp of D in the setUp of B to create those again? And even more complicated for A. – Ehsan Kia Sep 27 '13 at 07:29
  • In-order execution of separate test classes can be enforced with [Test Suites](http://stackoverflow.com/questions/7845929/has-junit4-begun-supporting-ordering-of-test-is-it-intentional). However, I'm still not sure why you want it and honestly doubt that it is a good idea. – Sven Amann Sep 27 '13 at 07:32
  • Okay, two ways around this: 1 - build an abstract test class for B with a factory method createInstance() that returns an instance of B and make your test for C extend this abstract test. Then move your instantiation of C into the factory-method implementation. – Sven Amann Sep 27 '13 at 07:32
  • 2 - Use something like [Mockito to create an instance of B directly](http://stackoverflow.com/questions/1087339/using-mockito-to-test-abstract-classes) – Sven Amann Sep 27 '13 at 07:35
0

You can use the @Before annotation to make a setup method to load the data structures before the tests are run. Each time a test will run, all the code in the setup method will be run first.

Tom Jonckheere
  • 1,630
  • 3
  • 20
  • 37
0

I recommend to keep all tests independent. The idea of unit testing is to test each unit under an exactly defined precondition completely isolated from other tests such as to be able to narrow down issues very easily. If your tests depend on setup from others and work on data that have been manipulated by other tests - imagine one test fails. How would you know what exactly went wrong? It might be the setup you used, or maybe your test fails because the data was wrongly modified by the precursor test which in turn appears successful, etc.

If you need to build complex data structures for test input for many tests, the Test Data Builder Pattern looks like a perfect fit:: http://www.natpryce.com/articles/000714.html

It would look something like:

public void test_SomeSpecificPropertyInB_WhenPreconditionIsLikeSoAndSo_ResultsInThisAndThat {
    // Arrange
    B sut = AbcdTreeBuilder.WithPreconditionLikeSoAndSo().Build();

    // Act
    SomeResultType result = sut.DoSomething();

    // Assert
    equals(...);
}
chiccodoro
  • 14,407
  • 19
  • 87
  • 130