问题
I am learning unit testing, I have some confusion, I have one Void method, Can you please explain to me how can I create a unit test for this method.
public void eat(Food food){
mAmountOfEatenFood += food.eatFood(mNeededAmountOfFood - mAmountOfEatenFood);
if(mAmountOfEatenFood == mNeededAmountOfFood){
System.out.println(mName + " has eaten " + mAmountOfEatenFood + " and will not be hungry for a while..");
mAmountOfEatenFood = 0;
mIsHungry = false;
}else{
System.out.println(mName + " has eaten " + mAmountOfEatenFood + " and is still hungry..");
System.out.println("Needs= " + mNeededAmountOfFood);
mIsHungry = true;
}
}
回答1:
This method looks like it changes the state of object which calls it, lets say the object is called FoodConsumer.
The eat(Food)
changes the state of two variables (mAmountOfEatenFood
and mIsHungry
).
So, to know if you need to feed that object again the getter method for mIsHungry
is needed. It would be good to have getter for mAmountOfEatenFood
.
The "obvious" result of eat(Food)
is if the object is still hungry.
In test method, you need to have an instance of FoodConsumer. Therefore, later after calling eat(Food)
you could call smth like isMHungry()
and assert if it's true or false. Additionally you could call getMAmountOfEatenFood()
to check if after eating insufficient amount of food it has proper value estimated by food.eatFood(....)
.
For a little simplification, you could change the eat(Food)
to boolean (even for test only) and return true/false just after setting the same value for mIsHungry
.
Next, some magic, which we can't see now happens in:
food.eatFood(mNeededAmountOfFood - mAmountOfEatenFood)
If this isn't any kind of library method and you have access to it, then it would be good to have tests convering if value returned by eatFood
is good.
I can't say exactly (because of magic in eatFood
), but it looks like there is on case uncovered by this method, what if the FoodConsumer over eats (I'm thinking of some conversion rate inside the eatFood
which could be over 1
).
For example, if neededFood
is 100
and eatenFood
is 90
, then the 10
goes to eatFood
which multiplicates that amount by 5
. So the eatenFood
is incremented with 50
resulting in 140
which is not equal with the amountOfNeededFood
.
Simple fix would be to just change your if
condition to:
if(mAmountOfEatenFood >= mNeededAmountOfFood){
In the end, lets compare this case witch something like repository.save(User)
.
Something similar to repo.save(User)
is a void method having only a side effects.
Those side effects aren't being explicitly shown when calling save
, but then the repo
must/should contain of methods which could return some values telling if the inner state of repo
was changed.
When testing the repository, to check if save
method works correctly, the assertions in test are checking if repository returns the same number of users which were saved and, for example, if the first/second/third user object contains the same values of the objects used when save
.
来源:https://stackoverflow.com/questions/59941543/create-junit-test-for-void-method