wood burning stoves 2.0*
The moose likes Testing and the fly likes Junit - inconsitant objects Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Engineering » Testing
Bookmark "Junit - inconsitant objects" Watch "Junit - inconsitant objects" New topic
Author

Junit - inconsitant objects

dave hopkins
Greenhorn

Joined: Oct 27, 2006
Posts: 25
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

Joined: Mar 22, 2008
Posts: 265

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.


There will always be people who are ahead of the curve, and people who are behind the curve. But knowledge moves the curve. --Bill James
Stevi Deter
Ranch Hand

Joined: Mar 22, 2008
Posts: 265

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

Joined: Oct 27, 2006
Posts: 25
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
internet detective
Marshal

Joined: May 26, 2003
Posts: 30353
    
150

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.


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
dave hopkins
Greenhorn

Joined: Oct 27, 2006
Posts: 25
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

Joined: Mar 22, 2008
Posts: 265

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
internet detective
Marshal

Joined: May 26, 2003
Posts: 30353
    
150

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

Joined: Jan 23, 2002
Posts: 11962
    
    5
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.


Author of Test Driven (2007) and Effective Unit Testing (2013) [Blog] [HowToAskQuestionsOnJavaRanch]
dave hopkins
Greenhorn

Joined: Oct 27, 2006
Posts: 25
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
internet detective
Marshal

Joined: May 26, 2003
Posts: 30353
    
150

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

Joined: Jul 11, 2001
Posts: 14112
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.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
ankur rathi
Ranch Hand

Joined: Oct 11, 2004
Posts: 3830
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
internet detective
Marshal

Joined: May 26, 2003
Posts: 30353
    
150

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

Joined: Oct 27, 2006
Posts: 25
Awesome responses guys!
vinita chauhan
Greenhorn

Joined: Mar 27, 2012
Posts: 1
hey do anyone have Junit test cases source code for this coffeemaker application??
please send me as soon as possible
regards
Jeanne Boyarsky
internet detective
Marshal

Joined: May 26, 2003
Posts: 30353
    
150

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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Junit - inconsitant objects