I have the following class where roll() generates random values of dice. All the other methods in the class depend on the values generated by roll(). How can I unit test the methods including roll() with JUnit, since the actual value is different each time roll() is called?
You can unit test roll() method by mocking the Math class. You will have to use your own implementation in place of Math.random(), but without changing any code in roll(). After providing your own random method you can test for other operations such as sort , or checking the range. You can also create your tests based on the assumptions of your roll method as it is slightly predictable.
To test other methods, you need to reduce coupling between them. You can create other helper methods for state management (in place of the private array you placed) and test them independantly.
As Sumit suggested, one solution would be to mock out the Math class so you have control over the value returned by the random() method. However as Math.random() is a static method you would have to use something like PowerMock to enable you to do this. Normal mocking frameworks like EasyMock, Mockito, JMock, etc don't support the mocking of static method calls. While this is very possible it does add a lot of bloat to your Unit Test setup.
Another solution would be to override the implementation of the roll() method in your test class. For example:
The downside of this technique is that you will need to create a second instance of Dice without overriding anything to test the roll() method.
There is no right and wrong answer here for which approach you choose to take. Go with whatever you're comfortable with and makes sense for you and your team.
Tim Driven Development
Anand A. Parikh
Joined: May 12, 2009
Thanks Sumit and Tim.
Using PowerMock with EasyMock, I was able to mock static method Math.random() in test class and unit test roll().
Then I created a helper method mockRoll() in test class to enable me to unit test toString() and sum().
As Tim suggested, if I changed the diceArray to package or protected access, I could override roll() in test class and unit test it that way too.