Java JUnit: Die Methode X ist für Typ Y nicht eindeutig

98

Ich hatte einige Tests, die gut funktionierten. Dann habe ich es in ein anderes Paket verschoben und erhalte jetzt Fehler. Hier ist der Code:

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"));
    }

Die Fehlermeldung lautet:

Die Methode assertEquals (Object, Object) ist für den Typ JGraphtUtilitiesTest nicht eindeutig

Wie kann ich das beheben? Warum ist dieses Problem aufgetreten, als ich die Klasse in ein anderes Paket verschoben habe?

Nick Heiner
quelle
Sagen Sie uns, wie Ihre Klasse deklariert ist. Sieht für mich so aus, als hätten Sie von JUnit3 geerbt und dann versucht, statisch von JUnit4 zu importieren.
Bmargulies
Ja, eigentlich hatte ich JUnit3 in Paket A und verwendete JUnit4 in Paket B, wo ich diese Tests ursprünglich geschrieben habe. Dann wechselte ich von Paket B zu Paket A, und das Problem trat auf. Aber ich sehe in dieser Klasse nichts, was auf JUnit 3 hinweisen würde. Wo wird das deklariert?
Nick Heiner
@Rosarch Sind diese JGraphtUtilities irgendwo verfügbar? Ich kann in JGraphT keine Methoden zur Erzeugung von Exzentrizitäten erkennen!
Nick

Antworten:

205

Die Methode assertEquals (Object, Object) ist für den Typ ... nicht eindeutig.

Dieser Fehler bedeutet, dass Sie ein doubleund und Doublean eine Methode übergeben, die zwei verschiedene Signaturen hat: assertEquals(Object, Object)und assertEquals(double, double)beide dank Autoboxing aufgerufen werden können.

Um die Mehrdeutigkeit zu vermeiden, stellen Sie sicher, dass Sie entweder anrufen assertEquals(Object, Object)(indem Sie zwei Doppel übergeben) oder assertEquals(double, double)(indem Sie zwei Doppel übergeben).

In Ihrem Fall sollten Sie also Folgendes verwenden:

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

Oder:

assertEquals(70.0d, eccen.get("alpha").doubleValue());
Pascal Thivent
quelle
ok, oder ich könnte es einfach auf JUnit 4 anstelle von JUnit 3 umstellen. Wie mache ich das?
Nick Heiner
8
Die Lösung besteht nicht wirklich darin, von einer Version zur anderen zu wechseln. Helfen Sie stattdessen dem Compiler und beseitigen Sie die von mir vorgeschlagene Mehrdeutigkeit.
Pascal Thivent
1
Wie auch immer, sollte es nicht assertEquals sein (70.0d, eccen.get ("alpha")); ?
Haller
3
@mahller Ich bin mir nicht sicher, mit wem Sie sprechen, aber selbst wenn es korrekter ist als der OP-Code, ist es immer noch nicht eindeutig, ob die Version von JUnit beides enthält assertEquals(Object, Object)und assertEquals(double, double)was bei JUnit 4.4, 4.5 der Fall ist. Aber wie gesagt, das Ändern der Version von JUnit ist nicht die wirkliche Lösung. Beheben Sie einfach das Problem.
Pascal Thivent
1
@Rosarch In diesem speziellen Fall ist es kein Problem in JUnit 3.8.1, es ist kein Problem in JUnit 4.3, es ist ein Problem in JUnit 4.4, es ist ein Problem in JUnit 4.5 (aber die Methode dauert 2) double ist veraltet), es ist kein Problem in JUnit 4.6 (die Methode wurde entfernt). Treffen Sie also Ihre Wahl, aber Sie sollten den Code korrigieren.
Pascal Thivent
1

Sie können die Methode verwenden

assertEquals(double expected, double actual, double delta)

Dabei werden Rundungsfehler berücksichtigt, die das Gleitkomma beeinträchtigen (siehe diesen Beitrag zum Beispiel). Du kannst schreiben

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

Dies bedeutet, dass die beiden Werte, solange sie sich für weniger als 0,0001 unterscheiden, als gleich angesehen werden. Dies hat zwei Vorteile:

  • Vergleicht Gleitkommawerte wie vorgesehen
  • Keine Notwendigkeit zu werfen, da die drei Argumente nur für Doppelte gelten, nicht für generische Objekte
Paolo
quelle
0

Die einfachste Lösung für dieses Problem besteht darin, den zweiten Parameter in ein Grundelement umzuwandeln:

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

Mehrdeutigkeit entfernt.

Dies gilt für alle Unterklassen von Number, zum Beispiel:

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

Würde auch eine Mehrdeutigkeit lösen.

AssertEquals (double, double) ist jedoch ab sofort und aus guten Gründen veraltet. Ich empfehle Ihnen daher, die Methode mit einem Delta zu verwenden, wie andere bereits vorgeschlagen haben.

Mit guten Gründen meine ich, dass sich angesichts der inneren Darstellung von Doppelzahlen zwei scheinbar gleiche Doppelzahlen in einem irrelevanten infinitesimalen Bruch unterscheiden können und keinen Test bestehen würden, aber das bedeutet nicht, dass etwas mit Ihrem Code nicht stimmt.

Fran Marzoa
quelle