0

I'm working on this little Java practice project where I'm supposed to program a sort of dating app... We have these online unit tests to check our work, and I always like to test each method and class that I write before going forward. On one of the first classes, a couple of methods aren't passing the tests, and I can't figure out why I tried a lot of different things. The first method is called getTitle, and it's just a normal getter method, which gets me back the value assigned to the title in the constructor (See code down below). The second method that's not passing is the .equals method which I had to overwrite. I'll post the errors I'm getting down below after the respective codes.

Here is the constructor for that class:

public class Interest {
private String title;
private Map<String, Float> alternatives;

public Interest(String title, Map<String, Float> alternatives)
{
    if (title.isEmpty()) //Title must contain something.
        throw new IllegalArgumentException();
    if (alternatives == null) //If alternatives points at null, I have to create an empty map.
        this.alternatives =  new HashMap<String, Float>();
    else
    {
        this.alternatives = new HashMap<String, Float>(alternatives); //Map must be a copy. 
        this.title = title; //This is where my problem is happening.
    }
}

Here is the code for the getTitle method:

    public String getTitle() 
{
    return this.title;
}

The test keeps saying:

testGetTitle

Cause of failure:
java.lang.AssertionError: expected:<Family Guy> but was:<null>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:743)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
at TestInterest.testGetTitle(TestInterest.java:56)

I tried a few different things, like in the constructor I tried creating a copy of the String, or in the getTitle method, I tried to return a new String(this.title), but I still got the same error... I also tried using Concat, but it didn't work.

And the test just tries to run the program with pre-assigned values and tests for each method.

The second method I have a problem with is the following:

    @Override
public boolean equals(Object obj)
{
    if (obj == this) 
        return true;
    if (!(obj instanceof Interest)) {
        return false;
    }

    if (obj instanceof Interest && this.title == ((Interest) obj).getTitle() && this.alternatives == ((Interest) obj).getAlternatives())
        return true;
    if (this == (Interest) obj)
        return true;
    else 
        return false; 
}

It keeps telling me:

testEqualsObject

Cause of failure:
java.lang.AssertionError: Two Interests should be equal when identical.
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.assertTrue(Assert.java:41)
at TestInterest.testEqualsObject(TestInterest.java:104)

I thought I considered all options of equality but not sure..

Any help would be appreciated, I don't have that much programming experience, and I'm trying to learn Java, and it gets frustrating sometimes with all of these unit tests...


Entire class code if it helps:

package jpp.exams.dating;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Interest {
private String title;
private Map<String, Float> alternatives;

public Interest(String title, Map<String, Float> alternatives)
{
    if (title.isEmpty() && title != null) //Title must contain something.
        throw new IllegalArgumentException();
    if (alternatives == null) //If alternatives points at null, I have to create an empty map.
        this.alternatives =  new HashMap<String, Float>();
    else
    {
        this.alternatives = new HashMap<String, Float>(alternatives); //Map must be a copy. 
        this.title = title; //This is where my problem is happening.
    }
}

public String getTitle() 
{
    return this.title;
}

public Map<String, Float> getAlternatives()
{
    return new HashMap<String, Float>(alternatives);
}

public float matchAlternative(String alternative)
{
    if (alternative == null || title == null)
        throw new IllegalArgumentException();
    else if (title.equals(alternative))
        return 1f;
    else if (this.alternatives.containsKey(alternative))
        return (float) this.alternatives.get(alternative);
    else 
        return 0f;
}

@Override
public String toString()
{
    String s = title + "\n";

    for (Map.Entry<String, Float> entry : this.alternatives.entrySet()) {
        String key = entry.getKey();
        Float f = entry.getValue();
        s = s.concat("\t" + key + ": " + f + "\n");
    }
    s = s.substring(0, s.length() - 1); //removes last new line

    return s;
}

@Override
public boolean equals(Object obj)
{
    if (obj == this) 
        return true;
    if (!(obj instanceof Interest)) {
        return false;
    }

    if (obj instanceof Interest && this.title == ((Interest) obj).getTitle() && this.alternatives == ((Interest) obj).getAlternatives())
        return true;
    if (this == (Interest) obj)
        return true;
    else 
        return false; 
}

public int hashCode()
{
    return Objects.hash(title);
}

}

11
  • 2
    Because you're only assigning it in one branch..... Commented Mar 1, 2017 at 22:11
  • Can you explain further please? Commented Mar 1, 2017 at 22:13
  • Note also that you invoke title.isEmpty() without checking whether title is null. This risks an NPE. Commented Mar 1, 2017 at 22:13
  • For your second question, read stackoverflow.com/questions/513832/…. For your first question, post the code of the class, and post the code of the test. Commented Mar 1, 2017 at 22:14
  • 1
    It's not bad code practice NOT to check for nullness if an NPE is thrown anyway when null is passed (it's only required when unexpected state would silently occur otherwise) Commented Mar 1, 2017 at 22:14

2 Answers 2

2

About the null title: In the constructor, you only assign a value to title if alternatives isn't null. Take the this.title = title; part out of the else block.

About the equals method: You did some comparisons with == where you should've used .equals, so change

if (obj instanceof Interest && this.title == ((Interest) obj).getTitle() && this.alternatives == ((Interest) obj).getAlternatives())

to

if (this.title.equals(((Interest) obj).getTitle()) && this.alternatives.equals(((Interest) obj).getAlternatives()))

(You'll notice I also removed the instanceof-check. It's not necessary there since you would've already returned if that was false)

Sign up to request clarification or add additional context in comments.

Comments

0

Issue is that you are instantiating the class with alternatives = null

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.