2016-10-29 4 views
0

그래서 JUnit의 내 테스트가 실패하는 이유를 알아 내는데 어려움을 겪고 있습니다. Bill 클래스, Money 클래스 및 Date 클래스가 있습니다. 새로운 Bill 목적은 테스트 및 누출 접근기 메서드를 수정하는 방법?

assertTrue(myBill.getAmount().getCents() == 0); 

실패되는 라인에 생성 될있다. 그래서 나는 그것이 어디에서 일어나는지 알고있다. 그러나 그것을 고치는 방법을 정확히 모르겠다. 내가 대신

return dueDate; 

return new Date(dueDate); 

같은 것들을 내 뮤 테이터 방법을 변경 시도했지만 여전히의 JUnit에 실패합니다. 도와주세요!

테스트 코드 :

@Test 
public void testBillConstructorPrivacyLeak() 
{ 
    Date date1 = new Date(1, 1, 2020); 
    Money money1 = new Money(10); 
    Bill myBill = new Bill(money1, date1, "sam"); 

    date1.setYear(2021); 
    money1.setMoney(5, 10); 

    //Now get values and make sure they have not changed 
    assertTrue(myBill.getAmount().getCents() == 0); 
    assertTrue(myBill.getDueDate().getYear() == 2020); 
} 

내 클래스 :

public class Bill 
{ 
private Money amount; 
private Date dueDate; 
private Date paidDate; 
private String originator; 

//paidDate set to null 
public Bill (Money amount, Date dueDate, String originator) { 
    this.amount = amount; 
    this.dueDate = dueDate; 
    this.originator = originator; 
    paidDate = null; 
} 

//copy constructor 
public Bill (Bill toCopy) { 
    this.amount = toCopy.amount; 
    this.dueDate = toCopy.dueDate; 
    this.paidDate = toCopy.paidDate; 
    this.originator = toCopy.originator; 
} 

public Money getAmount() { 
    return new Money(amount); 
} 

public Date getDueDate() { 
    return new Date(dueDate); 
} 

public String getOriginator() { 
    return originator; 
} 

//returns true if bill is paid, else false 
public boolean isPaid() { 
    return (paidDate != null); 
} 

//if datePaid is after the dueDate, the call does not update anything and returns false. 
//Else updates the paidDate and returns true 
//If already paid, we will attempt to change the paid date. 
public boolean setPaid (Date datePaid) { 
    if (datePaid.isAfter(dueDate)) { 
     return false; 
    } 
    else { 
     paidDate = new Date(datePaid); 
     return true; 
    } 
} 

//Resets the due date – If the bill is already paid, this call fails and returns false. 
//Else it resets the due date and returns true. 
public boolean setDueDate (Date newDueDate) { 
    if (isPaid()) { 
     return false; 
    } 
    else { 
     dueDate = new Date(newDueDate); 
     return true; 
    } 
} 

//Change the amount owed. 
//If already paid returns false and does not change the amount owed else changes 
//the amount and returns true. 
public boolean setAmount (Money amount) { 
    if (isPaid()) { 
     return false; 
    } 
    else { 
     amount = new Money(amount); 
     return true; 
    } 
} 

public void setOriginator (String originator) { 
    this.originator = originator; 
} 

//Build a string that reports the amount, when due, to whom, if paid, and if paid 
//the date paid 
public String toString() { 
    return "Amount: " + amount + " Due date: " + dueDate + " To: " + "originator" + " Paid?" + isPaid() + "Paid date: " + paidDate; 
} 

//Equality is defined as each field having the same value. 
public boolean equals (Object toCompare) { 
    if (toCompare instanceof Bill) { 
     Bill that = (Bill) toCompare; 
     return this.amount.equals(that.amount) && 
       this.dueDate.equals(that.dueDate) && 
       this.paidDate.equals(that.paidDate) && 
       this.originator.equals(that.originator); 
    } 
    return false; 
} 

}

public class Money 
{ 
private int dollars; 
private int cents; 

//Constructor which sets the dollar amount, and sets cents to 0 
//If the user enters in an amount LT 0, you will throw an IllegalArgumentException 
public Money (int dol) { 
    if (dol < 0) { 
     throw new IllegalArgumentException ("Must be greater than 0."); 
    } 
    this.dollars = dol; 
    cents = 0; 
} 

//Constructor which initialized dollars and cents. 
//If the user enters in an amount LT 0, you will throw an IllegalArgumentException 
public Money (int dol, int cent) { 
    if (dol < 0 || cent < 0) { 
     throw new IllegalArgumentException ("Must be greater than 0."); 
    } 
    this.dollars = dol; 
    this.dollars += cent/100; 
    this.cents = cent % 100; 
} 

//Copy constructor 
public Money (Money other) { 
    this.dollars = other.dollars; 
    this.cents = other.cents; 
} 

public int getDollars() { 
    return dollars; 
} 

public int getCents() { 
    return cents; 
} 

//If the user enters in an amount LT 0, you will throw an IllegalArgumentException 
public void setMoney (int dollars, int cents) { 
    if (dollars < 0 || cents < 0) { 
     throw new IllegalArgumentException ("Must be greater than 0."); 
    } 
    this.dollars = dollars; 
    this.dollars += cents/100; 
    this.cents = cents % 100; 
} 

//Gets the money amount as a double 
//For example it might return 5.75 
public double getMoney() { 
    return dollars + (cents/100.0); 
} 

//If the user enters in an amount LT 0, you will throw an IllegalArgumentException4 
public void add (int dollars) { 
    if (dollars < 0) { 
     throw new IllegalArgumentException ("Must be greater than 0."); 
    } 
    this.dollars += dollars; 
} 

//If the user enters in an amount LT 0, you will throw an IllegalArgumentException 
public void add (int dollars, int cents) { 
    if (dollars < 0 || cents < 0) { 
     throw new IllegalArgumentException ("Must be greater than 0."); 
    } 
    this.dollars += dollars; 
    this.cents += cents; 
    this.dollars += this.cents/100; 
    this.cents = this.cents % 100; 
} 

//Adds the amounts in other to our money object – reducing cents appropriately. 
public void add (Money other) { 
    this.dollars += other.dollars; 
    this.cents += other.cents; 
    this.dollars += this.cents/100; 
    this.cents = this.cents % 100; 
} 

//Two money objects are the same if they have the same value for dollars and cents. 
public boolean equals (Object o) { 
    if(o instanceof Money) { 
     return this.dollars == ((Money)o).dollars && this.cents == ((Money)o).cents; 
    } 
    return false; 
} 

//Prints out the amount as a string IE “$3.75” or “$4.00” Note the number of digits displayed for cents. 
//Again for testing and grading purposes use this EXACT output format 
public String toString() { 
    String c = String.format("%.02d",cents); 
    return "$" + dollars + "." + c; 
} 

} 사실에서

+0

테스트는 실제로 무엇을 테스트합니까? 코드가 잘못된 값을 반환합니까? 잘못된 값의 출처를 확인하기 위해 디버거의 코드를 밟았습니까? –

+0

값이 변경되었는지 확인하는 테스트입니다. 그러나 테스트에서 새로운 값을 할당합니다. Money 클래스의 생성자에서 0으로 설정되기 때문에 cents 값은 0이어야합니다. 그러나 테스트에서 10으로 설정하고 따라서 실패합니다. 나는 그것을 고치는 법을 모른다. –

+0

디버거 사용에 익숙하지 않습니다. JUnit에서는 다른 것으로 설정되기 때문에 실패하는 것입니다. 클래스 자체에는 아무런 문제가 없습니다. 그것이 외부 소스에서 바뀔 때까지. –

답변

2

당신의 문제가 결과가 Bill 요에 대한 생성자 u 참조MoneyDate 개체에 저장합니다. 그런 다음 테스트 케이스에서 해당 객체를 수정하면 동일한 객체가 수정됩니다.

public Bill (Money amount, Date dueDate, String originator) { 
    this.amount = new Money(amount); 
    this.dueDate = new Date(dueDate); 
    this.originator = originator; 
    paidDate = null; 
} 

당신은이 작업을 수행 할 필요가 없습니다 : 당신이 그 행동을하지 않으려면

당신은 깊은 사본 Bill 생성자의 MoneyDate 객체의, 즉을해야 originator 문자열은 불변이므로

+0

"this.amount = toCopy.amount"를 "this.amount = new Money (toCopy.amount)"로 변경하려고 시도했지만 작동하지 않았습니다 ... 내가 수행해야하는 다른 작업이 있습니까? –

+0

당신은 잘못된 생성자를보고 있습니다 ... 그렇습니다. 생성자는 동일한 변경 사항을 적용해야합니다. 내 업데이트 답변을 참조하십시오. –

+0

오, 나는 원래 생성자가 아니라 복사 생성자에서 그냥하고 있었다. 고맙습니다!!!!! –

1

Money 클래스의 구현을 표시하지 않지만 setMoney 메서드가 있다는 사실은 변경할 수 있음을 나타냅니다. 이 경우 Bill의 생성자가 전달 된 객체의 복사본을 만들지 않아서 money1을 변경하면 상태가 myBill으로 변경됩니다. 비슷한 말도 Date 개체에 적용됩니다.

는 다음과 같이 코드를 수정 해보십시오 : 일반적으로

public Bill (Money amount, Date dueDate, String originator) { 
    this.amount = new Money(amount); // needs copy-constructor for Money 
    this.dueDate = new Date(dueDate); // likewise for Date 
    this.originator = originator;  // no copying needed as String is immutable 
    paidDate = null; 
} 

//copy constructor 
public Bill (Bill toCopy) { 
    // Make copies also in the copy-constructor 
    this.amount = new Money(toCopy.amount); 
    this.dueDate = new Date(toCopy.dueDate); 
    this.paidDate = (toCopy.paidDate == null) ? null : new Date(toCopy.paidDate); 
    this.originator = toCopy.originator; 
} 

를, 당신의 오브젝트가 변하는로 설계하면 생성자에서 다른 곳 수비에 복사하는 것을 의미합니다.

한편, 객체를 불변으로 설계하는 것이 이러한 문제를 피하는 것이 더 좋습니다 (사실 "Joshua Bloch"가 "Effective Java"책에서 제시 한 조언). 그러나 Java가 ' 그 (것)들로 당신을 다량도 도움이되고 당신이 그 (것)들을 맞은 얻기에 확실히 클립을 위해 고투 할 것 같다.

이 디자인 접근 방식을 사용하면 더 좋은 출발점을 찾기 위해 http://immutables.github.io/ 라이브러리를 살펴 보는 것이 좋습니다. 내가 코드를 복제하려고 할 때

0

, 나는이 라인에서 오류가 점점 오전 :

public Date getDueDate() { 
return new Date(dueDate); 
} 

당신이 사용하고있는 날짜 생성자 알려 주시기 바랍니다 수 있습니다. java.util.date에는 Date를 인수로 취하는 생성자가 없습니다. 디버깅을 계속 진행하고 쿼리에 답변 할 수 있도록 자세히 설명하십시오.

감사합니다.

+0

나는 실제로 그것을 이미 알아 냈다! 하지만 그것은 Java를 사용하는 대신 내 자신의 Date 클래스 (할당 요구 사항의 일부)를 작성했기 때문입니다. –