File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
Win a copy of Soft Skills: The software developer's life manual this week in the Jobs Discussion forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Junit - inconsitant objects

 
dave hopkins
Greenhorn
Posts: 25
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey guys! Have been doing some experimenting junit today but have hit a wee wall! I have the following code which I downloaded from a University website. I don't think you need to read any of the CoffeeMaker code to answer my question, but if you'd like to:
http://open.ncsu.edu/se/tutorials/junit/



My first test "testAddRecipe" works as expected, so I would then assume the second test "testDeleteRecipe" to work but it fails. I have traced the code through and it seems as though the CoffeeMaker object is reset after the end of the first test. There is no tearDown() method defined so I cannot see why this would happen?
 
Stevi Deter
Ranch Hand
Posts: 265
Hibernate Java Spring
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave,

I think if you debug through the actual code in deleteRecipe, you'll discover
why the call to deleteRecipe is returning false and your test is failing.
 
Stevi Deter
Ranch Hand
Posts: 265
Hibernate Java Spring
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I almost forgot the more important issue here.

You indicate your assumption that your test cases will run in the same order they are in the java file. This is explicitly not true for JUnit. There is no guarantee of the order in which they are run.

Which leads to a more important point: your test cases should be atomic. They should never rely on the side effect of another test. This forces more thorough testing, and prevents bugs from creeping in through this assumption.
 
dave hopkins
Greenhorn
Posts: 25
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Stevi Deter:
Dave,

I think if you debug through the actual code in deleteRecipe, you'll discover
why the call to deleteRecipe is returning false and your test is failing.


Hmmm, nope still think it should suceed. We have:


So r1 is first passed to add recipe then the same r1 reference is passed to deleteRecipe. Therefore at some point this will be true

and so the method will eventually return true. I honestly don't see any other way for this to work???

cheers!
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 33667
316
Eclipse IDE Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by dave hopkins:
So r1 is first passed to add recipe then the same r1 reference is passed to deleteRecipe. Therefore at some point this will be true

This assumption is not correct. JUnit creates separate objects for each test case - at least in the version I tried. Which means you don't have the same reference to r1. Also, you have no way of being sure the add test runs before the delete test.
 
dave hopkins
Greenhorn
Posts: 25
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, you have no way of being sure the add test runs before the delete test.


I agree we should not be making assumptions about the order in which test cases are run but I can see for myself they are being run in the order they are written, so let us just assume this to be true for now.

This assumption is not correct. JUnit creates separate objects for each test case - at least in the version I tried.


Look at the code. I create r1 in the Test Object's contructor. What I believe you are referring to is the setUp() and tearDown() methods which is not what is being done here.

Thanks!
 
Stevi Deter
Ranch Hand
Posts: 265
Hibernate Java Spring
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave,

If you run the test even creating and adding the new recipe to the coffee maker as part of the same test case for deleting, you will never return true from delete recipe.

Check the for loop and check your assumptions about how the code works.
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 33667
316
Eclipse IDE Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by dave hopkins:
Look at the code. I create r1 in the Test Object's contructor. What I believe you are referring to is the setUp() and tearDown() methods which is not what is being done here.

No. I stand by my statement. I just ran the following inJUnit 4.1 and JUnit 4.4. In both, the constructor is executed twice. JUnit is creating a separate test object for each test case. We shouldn't rely on this behavior as it could change in the future. However, state cannot be shared in this way across tests even in the same test object.

 
Lasse Koskela
author
Sheriff
Posts: 11962
5
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can verify what Jeanne's saying:

1) JUnit creates a new instance of the test class for each test method.

2) JUnit developers have explicitly and officially told the community (can't remember through which channel) that there is no guarantee whatsoever that the order of test execution would be the same. It just looks like that because of the current implementation but it's not guaranteed.
 
dave hopkins
Greenhorn
Posts: 25
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for that guys. But if the constructor is run before every test

Originally posted by Lasse Koskela:
I can verify what Jeanne's saying:

1) JUnit creates a new instance of the test class for each test method.


why is there a setUp() method?

thanks!
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 33667
316
Eclipse IDE Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by dave hopkins:
Thanks for that guys. But if the constructor is run before every test

why is there a setUp() method?

The constructor for each test is run at the beginning. The setup is run after all the constructors are run. If the tests use a lot of memory or set up state in the database (for integration tests), it is good to have them run immediately before test execution. When there are thousands of tests memory issues could occur. (They haven't for us, but they could.) And for the database, the setUp can't be done all at once because the tests might need different data.

Also, the JUnit founders have not guaranteed that a new object will be created for each test forever. It happens to be that way at this time and I suspect it will stay that way for a long time. But they have the flexibility to change things.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jeanne Boyarsky:

Also, the JUnit founders have not guaranteed that a new object will be created for each test forever. It happens to be that way at this time and I suspect it will stay that way for a long time. But they have the flexibility to change things.


In fact I actually think that this depends on the runner you are using. As far as I know, a runner is allowed to reuse test instances when rerunning tests.
 
ankur rathi
Ranch Hand
Posts: 3830
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jeanne Boyarsky:

The constructor for each test is run at the beginning. The setup is run after all the constructors are run. If the tests use a lot of memory or set up state in the database (for integration tests), it is good to have them run immediately before test execution. When there are thousands of tests memory issues could occur. (They haven't for us, but they could.) And for the database, the setUp can't be done all at once because the tests might need different data.





I didn't get it.

If constructor runs for each test method (test case) then it's same as setUp() method. What's the difference?
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 33667
316
Eclipse IDE Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by ankur rathi:
If constructor runs for each test method (test case) then it's same as setUp() method. What's the difference?

It's more subtle than that. The constructor happens to run for each test method in the current text runner implementation that comes with JUnit 4. (and the Eclipse runner and likely many others.) It is not guaranteed to behave that way. The setUp method is guaranteed to run for each test method. The constructor makes not such guarantee.

This means that code relying on the constructor executing at a certain point is not portable and could break in the future.

Originally posted by ankur rathi:
In fact I actually think that this depends on the runner you are using. As far as I know, a runner is allowed to reuse test instances when rerunning tests.

Makes sense. I was referring to the built in runner. I agree a runner could reuse instances since that is consistent with the "no guarantee."
 
dave hopkins
Greenhorn
Posts: 25
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Awesome responses guys!
 
vinita chauhan
Greenhorn
Posts: 1
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hey do anyone have Junit test cases source code for this coffeemaker application??
please send me as soon as possible
regards
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 33667
316
Eclipse IDE Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
vinita chauhan wrote:hey do anyone have Junit test cases source code for this coffeemaker application??
please send me as soon as possible
regards

Why? It sounds like you are asking for help with homework.
 
Consider Paul's rocket mass heater.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic