Sto scrivendo una classe di test per la mia classe GiftSelector
utilizzando JUnit in BlueJ. Quando eseguo il metodo testGetCountForAllPresents()
, ho un NullPointerException
sulla linea:Perché sto ricevendo un NPE che appare solo occasionalmente quando il programma è in esecuzione?
assertEquals(true, santasSelector.getCountsForAllPresents().get(banana) == 3);
La cosa strana di questo NPE, è che sembra raramente quando si esegue il test di una volta, ma appare spesso la seconda volta che corro il test. A volte non appare finché non eseguo il test 7-8 volte consecutivamente.
Il messaggio di errore che sto ottenendo è: nessun messaggio di eccezione.
NPE alla linea 215 in GiftSelectortest.testGetCountForAllPresents
Il codice per la mia classe di test è:
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* The test class GiftSelectorTest. The GiftSelector that you are
* testing must have testMode enabled for this class to function.
* This is done in the setUp() method.
*/
public class GiftSelectorTest
{
private GiftList giftList1;
private GiftList giftList2;
private GiftList giftList3;
private Child jack;
private Child bob;
private Child dave;
private Child naughty1;
private GiftSelector santasSelector;
private Present banana1;
private Present orange;
private Present banana;
private Present apple;
private Present bike;
private Present doll;
private Present got;
private Present pearlHarbour;
private Present dog;
private Present cat;
private Present ball;
private Present heineken;
/**
* Default constructor for test class GiftSelectorTest
*/
public GiftSelectorTest()
{
//Nothing to do here...
}
/**
* Sets up the test fixture.
*
* Called before every test case method.
*/
@Before
public void setUp()
{
santasSelector = new GiftSelector();
santasSelector.setTestMode(true);
jack = new Child("Jack", 20, "1 A Place", true, true, true, false);
bob = new Child("Bob", 10, "2 A Place", true, true, true, true);
dave = new Child("Dave", 10, "3 A Place", true, true, true, true);
naughty1 = new Child("John", 5, "4 A Place", true, true, true, true);
giftList1 = new GiftList(jack);
giftList2 = new GiftList(bob);
giftList3 = new GiftList(dave);
banana = new Present("banana", "fruit", 10);
orange = new Present("orange", "fruit", 10);
banana1 = new Present("banana", "fruit", 10);
apple = new Present("apple", "fruit", 10);
bike = new Present("bike", "toy", 200);
doll = new Present("doll", "toy", 40);
got = new Present("game of thrones", "dvd", 50);
pearlHarbour = new Present("pearl harbour", "dvd", 20);
dog = new Present("dog", "animal", 100);
cat = new Present("cat", "animal", 80);
ball = new Present("ball", "toy", 5);
heineken = new Present("heineken", "beer", 1.60);
}
/**
* Tears down the test fixture.
*
* Called after every test case method.
*/
@After
public void tearDown()
{
//Nothing to do here...
}
@Test
public void testGetCountForAllPresents()
{
System.out.println(santasSelector.getCountsForAllPresents());
//Test on empty GiftSelector
assertNull(santasSelector.getCountsForAllPresents());
//Test on a GiftSelector with one giftlist containing one present
giftList1.addPresent(banana);
santasSelector.addGiftList(giftList1);
System.out.println(santasSelector.getCountsForAllPresents());
assertEquals(true, santasSelector.getCountsForAllPresents().get(banana) == 1);
//Test when GiftSelector contains 2 giftlists, each containing the same present object
giftList2.addPresent(banana);
santasSelector.addGiftList(giftList2);
System.out.println(santasSelector.getCountsForAllPresents());
assertEquals(true, santasSelector.getCountsForAllPresents().get(banana) == 2);
//Test when GiftSelector contains 3 giftlists, 2 containing the same present object and another containing an identical present but with a different present instance
giftList3.addPresent(banana1);
santasSelector.addGiftList(giftList3);
System.out.println(santasSelector.getCountsForAllPresents());
assertEquals(true, santasSelector.getCountsForAllPresents().get(banana) == 3); //This is the line I get the NPE
//Test when GiftSelector contains 3 giftLists, the first with one with a banana, the second with a banana and apple, and the third with a banana1 and ball
giftList2.addPresent(apple);
giftList3.addPresent(ball);
System.out.println(santasSelector.getCountsForAllPresents());
assertEquals(true, santasSelector.getCountsForAllPresents().get(banana) == 3);
assertEquals(true, santasSelector.getCountsForAllPresents().get(apple) == 1);
assertEquals(true, santasSelector.getCountsForAllPresents().get(ball) == 1);
}
@Test
public void testGetMostPopularPresent()
{
//Test on empty GiftSelector
assertNull(santasSelector.getMostPopularPresent());
//Test on a GiftSelector with one giftList and one Present
giftList1.addPresent(heineken);
santasSelector.addGiftList(giftList1);
assertEquals(true, santasSelector.getMostPopularPresent().comparePresent(heineken));
//Tset on a GiftSelector with 1 giftList and 2 presents, one more expensive than the other
giftList1.addPresent(banana);
assertEquals(true, santasSelector.getMostPopularPresent().comparePresent(banana));
//Test on a GiftSelector with 1 giftList and 3 presents. Banana and Apple are equal in price, and are both in the top3,
//therefore it should return the present closest to the start of the list
giftList1.addPresent(apple);
assertEquals(true, santasSelector.getMostPopularPresent().comparePresent(banana) || santasSelector.getMostPopularPresent().comparePresent(apple));
//Test on a GiftSelector with 2 giftLists, the second list containing banana1, an indentical present to banana
giftList2.addPresent(banana1);
santasSelector.addGiftList(giftList2);
assertEquals(true, santasSelector.getMostPopularPresent().comparePresent(banana));
//Test on a GiftSelector with 2 giftLists, the first containing four presents and the second containing 2 presents.
//This tests to see if top3 is working.
giftList1.addPresent(bike);
giftList2.addPresent(bike);
assertEquals(true, santasSelector.getMostPopularPresent().comparePresent(bike));
}
}
ho incluso solo i metodi di prova che fanno riferimento al metodo di getCountsForAllPresents()
. Si noterà che ho aggiunto dichiarazioni di stampa prima di ogni chiamata a un metodo assertEquals()
contenente il metodo getCountForAllPresents()
. La cosa interessante è che prima della riga in cui ottengo l'NPE, l'istruzione print stampa il valore corretto perrestituito da getCountForAllPresents()
.
L'unica altra cosa strana che ho notato, è che quando vado attraverso il metodo testGetCountForAllPresents()
utilizzando incorporato nel debugger, mi accorgo che giftList3
non appare nel santaMap
HashMap
in santasSelector
, eppure l'istruzione print ancora BlueJ stampa il conteggio corretto, implicando che deve conoscere giftList3
.
Il codice per getCountForAllPresents()
è:
/**
* For each present, calculate the total number of children who have asked for that present.
*
* @return - a Map where Present objects are the keys and Integers (number of children requesting
* a particular present) are the values. Returns null if santaMap is empty.
*/
public HashMap<Present, Integer> getCountsForAllPresents()
{
if(!santaMap.isEmpty()) {
//This HashMap contains a mapping from each unique real world present, represented by it's toComparisonString(), to a Present object representing it
HashMap<String, Present> uniquePresents = new HashMap<String, Present>();
//This HashMap contains a mapping from each Present object in uniquePresents to the number of times it's toComparisonString() is equal to another in santaMap
HashMap<Present, Integer> presentFrequency = new HashMap<Present, Integer>();
for(GiftList wishlist: santaMap.values()) {
for(Present present: wishlist.getAllPresents()) {
//Have we already seen this present?
if(uniquePresents.containsKey(present.toComparisonString())) {
//If so, update the count in presentFrequency
Integer tmp = presentFrequency.get(uniquePresents.get(present.toComparisonString()));
tmp++;
presentFrequency.put(uniquePresents.get(present.toComparisonString()), tmp);
} else {
//If not, add it to the maps uniquePresents and presentFrequency (with a frequency of 1)
uniquePresents.put(present.toComparisonString(), present);
presentFrequency.put(present, 1);
}
}
}
//Return a map with unique presents as keys and their frequencies as values
return presentFrequency;
}
else {
//If there are no mappings in Santa's map, return null
return null;
}
}
dovrei spiegare che santaMap
è un HashMap
, con un oggetto Child
come chiave e un oggetto GiftList
come valore. Fondamentalmente mappa un bambino nella lista dei desideri di Natale. Un santaMap
può contenere solo una lista dei desideri dello stesso bambino.
Non ho idea del motivo per cui sto ricevendo l'NPE, è qualcosa a che fare con il modo in cui ho scritto il metodo getCountForAllPresents()
? Come ho implementato il metodo/la classe di test?
Puoi aggiungere il codice per 'Present'? – RealSkeptic
dove si trova la riga 215 in cui si ottiene il valore null? –
Penso che il codice completo di 'GiftSelector' potrebbe essere una buona aggiunta –