'Hashtable, two test does not work with Junit

I have written a code where I implement a hashtable of a set interface. All of my tests I going through except these two below in the test class. I have included how I have written them. For the first test I get:

java.lang.AssertionError: 
Expected: <-1>
     but: was <0>
Expected :<-1>
Actual   :<0>

and then the second test I get:

java.lang.AssertionError: 
Expected: <0>
     but: was <10>
Expected :<0>
Actual   :<10>

I don't know what I am supposed to write/ change in the tests, so they work.

//EDIT: I added a test that has a similar code to the first test that I have a problem with. This test goes through.

//TODO: help me understand how I should write these two tests.

/**
 * An interface describing a generic set. Duplicates are not allowed.
 */
public interface Set<T> {

    boolean add(T elem);
    boolean remove(T elem);
    boolean contains(T elem);
    int size();
}

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import static java.util.Objects.hash;

/**
 * A hash table-based implementation of the Set interface.
 */
public class HashSet<T> implements Set<T> {
   private List<T>[] table;
    private int size;
    private int capacity;
    private int index;



     /**
     * Creates a hash table with the given capacity (amount of buckets).
     *
     * @throws IllegalArgumentException if capacity <= 0.
     */
    public HashSet(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException(
                "capacity must be a positive, non-zero value! Provided: " + capacity);
        }
     @SuppressWarnings("unchecked") // for this declaration only
      List<T>[] t = new LinkedList[capacity];
      table = t;
      size = 0;
    }


    /**
     * Adds the given element to the set.
     *
     * Complexity: O(1) expected time.
     *
     * @param elem An element to add to the set.
     * @return true if the set did not contain the element, otherwise false.
     */
    @Override
    public boolean add(T elem) {
    if (elem == null || elem.equals("")){
            return false;
        }

        int hash = Math.abs(elem.hashCode() % table.length);

        if (table[hash]== null){
            table[hash] = new LinkedList<T>();
            table[hash].add(elem);
            size ++;
            return true;
        }
        if (table[hash].contains(elem)){
            return false;
        }else{
            table[hash].add(elem);
            size++;
            return true;
        }
    }

    /**
     * Removes the given element from the dictionary, if it is present.
     *
     * Complexity: O(1) expected time.
     *
     * @param elem An element to remove from the set.
     * @return true if the set contained the element, false otherwise.
     */
    @Override
    public boolean remove(T elem) {
        if (elem == null || elem.equals("")){
            return false;
        }

        int hash = Math.abs(elem.hashCode() % table.length);

        if (table[hash] != null && table[hash].contains(elem)){
            table[hash].remove(elem);
            size --;
            return true;
        }else{
            return false;
        }
    }


    /**
     * Check if an element is in the Set.
     *
     * Complexity: O(1) expected time.
     *
     * @param elem An element to look for.
     * @return true if the element is in the set, false otherwise.
     */
    @Override
    public boolean contains(T elem) {
        if (elem == null || elem .equals("")){
            return false;
        }
        int hash = Math.abs(elem.hashCode() % table.length);

        if (table[hash] != null && table[hash].contains(elem)){
            return true;
        }else{
            return false;
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        HashSet<?> hashSet = (HashSet<?>) o;
        return capacity == hashSet.capacity && size == hashSet.size && index == hashSet.index && Objects.equals(table, hashSet.table);
    }

    @Override
    public int hashCode() {
        return hash(capacity, size, index, table);
    }

    /**
     * Returns the number of elements in this set.
     *
     * Complexity: O(1) expected time.
     *
     * @return The number of elements in this set.
     */
    @Override
    public int size() {
        return size;
    }
}

import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;

import java.util.Arrays;

/**
 * Test for the HashSet implementation of the Set interface. Runs both the
 * SetTest tests, as well as tests specific to hashing.
 *
 * This test class mostly contains only hash collision tests.
 */
public class HashSetTest extends SetTest {
    private Set<SingleHashUnequal> set;
    private SingleHashUnequal[] uniqueObjsWithEqualHashes;

    /**
     * Returns an implementation of Set that can hold at least 'minCapacity'
     * Integers.
     *
     * @param minCapacity The least amount of elements the Set must be able to
     * hold.
     * @return An implementation of Set.
     */
    @Override
    protected Set<Integer> getIntegerSet(int minCapacity) {
        return new HashSet<Integer>(minCapacity);
    }

    @Override
    @Before
    public void setUp() {
        // We are overriding the setUp method of SetTest, so we need to call
        // it explicitly to not break everything.
        super.setUp();

        int numDummies = 10;
        uniqueObjsWithEqualHashes = new SingleHashUnequal[numDummies];
        set = new HashSet<SingleHashUnequal>(numDummies * 2);
        for (int i = 0; i < numDummies; i++) {
            SingleHashUnequal dummy = new SingleHashUnequal();
            set.add(dummy);
            uniqueObjsWithEqualHashes[i] = dummy;
        }
    }

   @Test // similar test with the first test that I have a problem with.
    public void addUniqueElementsWithEqualHashesIncrementsSize() {
        // Arrange
        int capacity = uniqueObjsWithEqualHashes.length;
        Set<SingleHashUnequal> set = new HashSet<SingleHashUnequal>(capacity);
        int expectedSize = 0;
        for (SingleHashUnequal elem : uniqueObjsWithEqualHashes) {
            expectedSize++;
            // Act
            set.add(elem);
            // Assert
            assertThat(set.size(), equalTo(expectedSize));
        }
    }
    @Test
    public void removeUniqueElementsWithEqualHashesDecrementsSize() { //TESTT
        int capacity = uniqueObjsWithEqualHashes.length;
        Set<SingleHashUnequal> set = new HashSet<SingleHashUnequal>(capacity);
        int expectedSize = 0;
        for (SingleHashUnequal elem : uniqueObjsWithEqualHashes) {
            expectedSize--;
            // Act
            set.remove(elem);
            // Assert
            assertThat(set.size(), equalTo(expectedSize));
        }
    }

    @Test
    public void removeElementNotInSetWithCollidingHashDoesNotDecreaseSize() { //TESTT
        // Test that removing an element that is not in the set, but has the
        // same hash as some other element in the set, does not decrement size
        SingleHashUnequal elem = new SingleHashUnequal();
        int expectedSize = 0;
        set.remove(elem);
        assertThat(set.size(),equalTo(expectedSize));

    }
    /**
     * A helper class for testing hash collisions. Instances equal only
     * themselves and all instances have the same hashCode.
     */
    private static class SingleHashUnequal {
        private static final int HASH = 0;

        @Override
        public boolean equals(Object o) {

            return this == o;
        }

        @Override
        public int hashCode() {
            return HASH;
        }
    }
}


Solution 1:[1]

@Test
    public void removeUniqueElementsWithEqualHashesDecrementsSize() { //TESTT
        int capacity = uniqueObjsWithEqualHashes.length;
        Set<SingleHashUnequal> set = new HashSet<SingleHashUnequal>(capacity);
        int expectedSize = 0;
        for (SingleHashUnequal elem : uniqueObjsWithEqualHashes) {
            expectedSize--;
            // Act
            set.remove(elem);
            // Assert
            assertThat(set.size(), equalTo(expectedSize));
        }
    }

Something seems off about this test, according to your @Before, you are already creating a new set in the line set = new HashSet<SingleHashUnequal>(numDummies * 2);

however, in your test, you create a new object with the same name: Set<SingleHashUnequal> set = new HashSet<SingleHashUnequal>(capacity); Same Object type, same name. This is generally bad practice, I don't know if somehow the objects got mixed in the compiler, but that's probably not the case.

Regardless,

Set<SingleHashUnequal> set = new HashSet<SingleHashUnequal>(capacity);
        int expectedSize = 0;
        for (SingleHashUnequal elem : uniqueObjsWithEqualHashes) {
            expectedSize--;
            // Act
            set.remove(elem);

Here, you remove elements from a list that has no elements. According to your implementation, if the object you want to remove does not exist, nothing happens, all good. However, you still decrement expected size with expectedSize--. This means that even though nothing was removed, your size decreases to -1.

By then asserting if the values are equal, since the original size of the set still stands 0, and expected size stands at -1, it asserts that the code is wrong, even though it is the test that has its own problems.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dharman