Java JUnit: Metoda X jest niejednoznaczna dla typu Y

98

Niektóre testy działały dobrze. Następnie przeniosłem go do innego pakietu i teraz pojawiają się błędy. Oto kod:

import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.jgrapht.Graphs;
import org.jgrapht.WeightedGraph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleWeightedGraph;
import org.junit.*; 

@Test
    public void testEccentricity() {
        WeightedGraph<String, DefaultWeightedEdge> g = generateSimpleCaseGraph();
        Map<String, Double> eccen = JGraphtUtilities.eccentricities(g);

        assertEquals(70, eccen.get("alpha"));
        assertEquals(80, eccen.get("l"));
        assertEquals(130, eccen.get("l-0"));
        assertEquals(100, eccen.get("l-1"));
        assertEquals(90, eccen.get("r"));
        assertEquals(120, eccen.get("r-0"));
        assertEquals(130, eccen.get("r-1"));
    }

Komunikat o błędzie jest następujący:

Metoda assertEquals (Object, Object) jest niejednoznaczna dla typu JGraphtUtilitiesTest

Jak mogę to naprawić? Dlaczego wystąpił ten problem, gdy przeniosłem klasę do innego pakietu?

Nick Heiner
źródło
powiedz nam, w jaki sposób deklarowana jest Twoja klasa. Wydaje mi się, że odziedziczyłeś po JUnit3, a następnie próbowałeś statycznie zaimportować z JUnit4.
bmargulies
tak, właściwie miałem JUnit3 w pakiecie A i użyłem JUnit4 w pakiecie B, gdzie pierwotnie napisałem te testy. Potem przesiadłem się z pakietu B na pakiet A i pojawił się problem. Ale nie widzę w tej klasie niczego, co wskazywałoby na JUnit 3. Gdzie to jest zadeklarowane?
Nick Heiner
@Rosarch Czy te narzędzia JGraphtUtilities są dostępne gdziekolwiek? Nie widzę metod tworzenia dziwactw w JGraphT!
Nick

Odpowiedzi:

205

Metoda assertEquals (Object, Object) jest niejednoznaczna dla typu ...

Ten błąd oznacza, że ​​przekazujesz doublei i Doubledo metody, która ma dwa różne sygnatury: assertEquals(Object, Object)i assertEquals(double, double)oba można wywołać dzięki autoboxingowi.

Aby uniknąć dwuznaczności, upewnij się, że sprawdzasz (przekazując dwa dubli) assertEquals(Object, Object)lub assertEquals(double, double)(przekazując dwa dublety).

Tak więc w twoim przypadku powinieneś użyć:

assertEquals(Double.valueOf(70), eccen.get("alpha"));

Lub:

assertEquals(70.0d, eccen.get("alpha").doubleValue());
Pascal Thivent
źródło
ok, albo mógłbym po prostu przełączyć go na JUnit 4 zamiast JUnit 3. Jak to zrobić?
Nick Heiner
8
Rozwiązaniem nie jest tak naprawdę przejście z jednej wersji na drugą. Zamiast tego pomóż kompilatorowi i usuń niejednoznaczność, jak zasugerowałem.
Pascal Thivent
1
W każdym razie, czy nie powinno to być assertEquals (70.0d, eccen.get ("alpha")); ?
mhaller
3
@mahller Nie jestem pewien, z kim rozmawiasz, ale nawet jeśli jest to bardziej poprawne niż kod OP, nadal jest niejednoznaczne, jeśli wersja JUnit ma oba, assertEquals(Object, Object)a tak assertEquals(double, double)jest w przypadku JUnit 4.4, 4.5. Ale jak powiedziałem, zmiana wersji JUnit nie jest prawdziwym rozwiązaniem, po prostu napraw problem.
Pascal Thivent
1
@Rosarch W tym konkretnym przypadku to nie jest problem w JUnit 3.8.1, to nie jest problem w JUnit 4.3, to jest problem w JUnit 4.4, to jest problem w JUnit 4.5 (ale metoda przyjmuje 2 doubles jest przestarzałe), nie stanowi to problemu w JUnit 4.6 (metoda została usunięta). Więc dokonaj wyboru, ale powinieneś naprawić kod.
Pascal Thivent
1

Możesz użyć metody

assertEquals(double expected, double actual, double delta)

Który weźmie pod uwagę błąd zaokrąglania, który jest hinerent do zmiennoprzecinkowego (zobacz na przykład ten post ). Możesz pisać

assertEquals(70, eccen.get("alpha"), 0.0001);

Oznacza to, że tak długo, jak te dwie wartości różnią się o mniej niż 0,0001, są uważane za równe. Ma to dwie zalety:

  • Porównuje wartości zmiennoprzecinkowe zgodnie z oczekiwaniami
  • Nie ma potrzeby rzucania, ponieważ te trzy argumentowe twierdzenia dotyczą tylko podwójnych, a nie ogólnych obiektów
Paolo
źródło
0

Najprostszym rozwiązaniem tego problemu jest po prostu rzutowanie drugiego parametru na prymityw:

assertEquals(70, (double)eccen.get("alpha"));

Usunięto niejednoznaczność.

Dotyczy to wszystkich podklas Number, na przykład:

assertEquals(70, (int)new Integer(70));

Rozwiązałoby to również niejednoznaczność.

Jednak metoda assertEquals (double, double) jest obecnie przestarzała i nie bez powodu, dlatego zachęcam do korzystania z metody z deltą, jak sugerowali już inni.

Z dobrych powodów mam na myśli to, że biorąc pod uwagę wewnętrzną reprezentację liczb podwójnych, dwie pozornie równe liczby podwójne mogą różnić się nieistotnym, nieskończenie małym ułamkiem i nie przejdą testu, ale to nie znaczy, że coś jest nie tak z twoim kodem.

Fran Marzoa
źródło