Domanda

Qualcuno sa il motivo per cui JUnit 4 fornisce assertEquals(foo,bar) ma non assertNotEqual(foo,bar) metodi?

Fornisce assertNotSame (corrispondente a assertSame) e assertFalse (corrispondenti a assertTrue), così sembra strano che non hanno disturbato compreso assertNotEqual.

A proposito, so che JUnit-addons fornisce i metodi che sto cercando. Sto solo chiedendo per curiosità.

È stato utile?

Soluzione

Io suggerirei di utilizzare il assertThat() stile più recente afferma, che può facilmente descrivere tutti i tipi di negazioni e automaticamente costruire una descrizione di quello che ti aspettavi e che cosa avete ottenuto se l'asserzione fallisce:

assertThat(objectUnderTest, is(not(someOtherObject)));
assertThat(objectUnderTest, not(someOtherObject));
assertThat(objectUnderTest, not(equalTo(someOtherObject)));

Tutte e tre le opzioni sono equivalenti, scegliere quello che si trova più leggibile.

Per usare i semplici nomi dei metodi (e consentire questa sintassi teso al lavoro), è necessario che tali importazioni:

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

Altri suggerimenti

C'è un assertNotEquals in JUnit 4.11: https://github.com/junit-team/junit/blob/master/doc/ReleaseNotes4.11.md#improvements-to-assert-and-assume

import static org.junit.Assert.assertNotEquals;

Mi chiedo stesso. L'API di Assert non è molto simmetrica; a verificare che gli oggetti sono uguali, fornisce assertSame e assertNotSame.

Naturalmente, non è troppo tempo per scrivere:

assertFalse(foo.equals(bar));

Con una tale affermazione, l'unica parte informativa della produzione è, purtroppo, il nome del metodo di prova, messaggio in modo descrittivo dovrebbe essere formato separatamente:

String msg = "Expected <" + foo + "> to be unequal to <" + bar +">";
assertFalse(msg, foo.equals(bar));

Questo è, naturalmente in modo noioso, che è meglio per rotolare il proprio assertNotEqual. Per fortuna in futuro sarà forse parte della JUnit: problema JUnit 22

Direi che l'assenza di assertNotEqual è infatti un'asimmetria e fa un po 'meno JUnit apprendibile. Ricordate che questo è un caso accurato quando si aggiunge un metodo diminuirebbe la complessità delle API, almeno per me: Symmetry aiuta governare lo spazio più grande. La mia ipotesi è che il motivo per l'omissione può essere che ci sono troppo poche le persone che chiedono per il metodo. Eppure, mi ricordo un momento in cui anche assertFalse non esisteva; quindi, ho un'aspettativa positiva che potrebbe eventualmente aggiunto il metodo, dato che non è difficile; anche se riconosco che ci sono numerose soluzioni alternative, anche quelli eleganti.

Vengo a questo partito piuttosto tardi, ma ho scoperto che la forma:

static void assertTrue(java.lang.String message, boolean condition) 

può essere fatto per lavorare per la maggior parte 'non è uguale a' casi.

int status = doSomething() ; // expected to return 123
assertTrue("doSomething() returned unexpected status", status != 123 ) ;

Sto lavorando su JUnit in Java 8 ambiente, utilizzando jUnit4.12

per me: il compilatore non era in grado di trovare le assertNotEquals metodo, anche quando ho usato
    import org.junit.Assert;

Così ho cambiato
assertNotEquals("addb", string);
a
Assert.assertNotEquals("addb", string);

Quindi, se si trovano ad affrontare problema per quanto riguarda assertNotEqual non riconosciuto, quindi, trasformarlo in Assert.assertNotEquals(,); che dovrebbe risolvere il problema

L'ovvia ragione che la gente voleva assertNotEquals () è stato quello di confrontare i comandi incorporati senza doverli convertire in oggetti in piena regola prima:

esempio verbose:

....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....

vs.

assertNotEqual(1, winningBidderId);

Purtroppo dal momento che Eclipse non include JUnit 4.11 per impostazione predefinita è necessario essere prolisso.

Caveat Io non credo che il '1' deve essere avvolto in un Integer.valueOf (), ma dal momento che sto appena tornato da .NET non contare sulla mia correttezza.

E 'meglio usare la Hamcrest in quelle negative, piuttosto che assertFalse come nel primo rapporto di prova mostrerà un diff per il fallimento asserzione.

Se si utilizza assertFalse, basta avere un errore di asserzione nel rapporto. cioè perdita di informazioni sulla causa dell'errore.

Sono d'accordo totalmente con il punto di vista OP. Assert.assertFalse(expected.equals(actual)) non è un modo naturale per esprimere una disuguaglianza.
Ma direi che oltre Assert.assertEquals(), opere Assert.assertNotEquals() ma non è facile da usare per documentare ciò che il test in realtà afferma e per capire / debug come l'asserzione fallisce.
Quindi sì JUnit 4.11 e JUnit 5 fornisce Assert.assertNotEquals() (Assertions.assertNotEquals() in JUnit 5) ma ho davvero evitare di utilizzarle.

In alternativa, per affermare lo stato di un oggetto che generale uso un API matcher che scava nello stato oggetto facilmente, tale documento chiaramente l'intenzione delle affermazioni e che è molto facile da usare per capire la causa del fallimento asserzione.

Ecco un esempio.
Supponiamo che io sono una classe di animali che voglio provare il metodo createWithNewNameAndAge(), un metodo che crea un nuovo oggetto Animal cambiando il suo nome e la sua età, ma mantenendo il suo cibo preferito.
Supponiamo che io uso Assert.assertNotEquals() ad affermare che l'originale e nuovi oggetti sono diversi.
Qui è la classe degli animali con un'implementazione imperfetta di createWithNewNameAndAge():

public class Animal {

    private String name;
    private int age;
    private String favoriteFood;

    public Animal(String name, int age, String favoriteFood) {
        this.name = name;
        this.age = age;
        this.favoriteFood = favoriteFood;
    }

    // Flawed implementation : use this.name and this.age to create the 
    // new Animal instead of using the name and age parameters
    public Animal createWithNewNameAndAge(String name, int age) {
        return new Animal(this.name, this.age, this.favoriteFood);
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getFavoriteFood() {
        return favoriteFood;
    }

    @Override
    public String toString() {
        return "Animal [name=" + name + ", age=" + age + ", favoriteFood=" + favoriteFood + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((favoriteFood == null) ? 0 : favoriteFood.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Animal)) return false;

        Animal other = (Animal) obj;
        return age == other.age && favoriteFood.equals(other.favoriteFood) &&
                name.equals(other.name);
    }

}

JUnit 4.11+ (o JUnit 5) sia come prova runner e strumento affermazione

@Test
void assertListNotEquals_JUnit_way() {
    Animal scoubi = new Animal("scoubi", 10, "hay");
    Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
    Assert.assertNotEquals(scoubi, littleScoubi);
}

Il test ha esito negativo, come previsto, ma la causa fornito per lo sviluppatore non è veramente utile. Si dice solo che i valori devono essere diversi e in uscita il risultato toString() invocato sul parametro effettivo Animal:

  

java.lang.AssertionError: I valori devono essere diversi. Attuale: Animal

     

[name = Scoubi, età = 10, favoriteFood = fieno]

     

a org.junit.Assert.fail (Assert.java:88)

Ok gli oggetti non sono uguali. Ma dov'è il problema?
Quale campo non è valutato correttamente nel metodo collaudato? Uno ? Due ? Tutti loro?
Per scoprirlo bisogna scavare nella realizzazione createWithNewNameAndAge() / utilizzare un debugger, mentre l'API di test sarebbe molto più amichevole se si farebbe per noi il differenziale tra i quali è previsto e che si ottiene.


JUnit 4.11 come prova corridore e un'API prova Matcher strumento di affermazione

Qui lo stesso scenario di prova, ma che utilizza AssertJ (l'ottima prova Matcher API) per rendere l'affermazione dello stato Animal::

import org.assertj.core.api.Assertions;

@Test
void assertListNotEquals_AssertJ() {
    Animal scoubi = new Animal("scoubi", 10, "hay");
    Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
    Assertions.assertThat(littleScoubi)
              .extracting(Animal::getName, Animal::getAge, Animal::getFavoriteFood)
              .containsExactly("little scoubi", 1, "hay");
}

Naturalmente il test fallisce ancora ma questa volta il motivo è chiaramente indicato:

  

java.lang.AssertionError:

     

In attesa:

     

<[ "Scoubi", 10, "fieno"]>

     

per contenere esattamente (e nello stesso ordine):

     

<[ "piccolo Scoubi", 1, "fieno"]>

     

ma alcuni elementi non sono stati trovati:

     

<[ "piccolo Scoubi", 1]>

     

e gli altri non ci si aspettava:

     

<[ "Scoubi", 10]>

     

a junit5.MyTest.assertListNotEquals_AssertJ (MyTest.java:26)

Possiamo leggere che per valori Animal::getName, Animal::getAge, Animal::getFavoriteFood dell'animale tornati, ci aspettiamo di avere questi valori:

"little scoubi", 1, "hay" 

, ma abbiamo avuto questi valori:

"scoubi", 10, "hay"

Così sappiamo dove indagare: name e age non sono valutati correttamente. Inoltre, il fatto di specificare il valore hay nella asserzione di Animal::getFavoriteFood() permette anche di affermare più finemente la Animal restituito. Vogliamo che gli oggetti siano non è la stessa per alcune proprietà, ma non necessariamente per ogni proprietà.
Quindi sicuramente, utilizzando un'API matcher è molto più chiara e flessibile.

Modulo coerenza API, perché JUnit non ha fornito assertNotEquals() è la stessa ragione per cui JUnit mai fornito metodi come

  • assertStringMatchesTheRegex(regex, str) vs. assertStringDoesntMatchTheRegex(regex, str)
  • assertStringBeginsWith(prefix, str) vs. assertStringDoesntBeginWith(prefix, str)

vale a dire. non c'è fine a fornire una specifica modalità di asserzioni per il tipo di cose che si potrebbe desiderare nella logica affermazione!

Molto meglio per fornire le primitive di prova componibile come equalTo(...), is(...), not(...), regex(...) e lasciare che il pezzo programmatore quelli insieme invece per più leggibilità e la sanità mentale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top