Comment couvrir serialVersionUID par test unitaire

voix
0

J'ajoute des tests unitaires pour couvrir un projet java héritage,

Je sais comment tester l'unité et la couverture de cette classe, je l'ai fait en ajoutant le test unitaire ci-dessous.

public class Thing implements Serializable {

    private static final long serialVersionUID = -1463850548670691860L;

    private String id;
}

unsing par exemple:

classe ThingTest {

@Test
void testShouldNotChangeSerialVersionUID() throws NoSuchFieldException {
    final Field serialVersionUID = Thing.class.getDeclaredField(serialVersionUID);
    serialVersionUID.setAccessible(true);

    assertEquals(-1463850548670691860L, getField(serialVersionUID, new Thing()));
}

}

Mais le sonar et jacoco montrent serialVersionUID ne sont pas couverts. ce qui est du son.

entrez

Pourriez-vous s'il vous plaît suggérer une solution pour rendre heureux un sonar en couvrant ce champ.

Merci

Créé 14/01/2020 à 00:05
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
-1

Si dans votre JUnit vous étendez le ObjectInputString vous pouvez lire le serialVersionUID tout désérialisation l'objet sérialisé:

     private class MyObjectInputStream extends ObjectInputStream {

        public long uid;

        public MyObjectInputStream(InputStream in) throws IOException {
            super(in);
        }

        @Override
        protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
            ObjectStreamClass readClassDescriptor = super.readClassDescriptor(); //To change body of generated methods, choose Tools | Templates.
            uid = readClassDescriptor.getSerialVersionUID();
            return readClassDescriptor;
        }



    }

    @Test
    public void testSomeMethod() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
        oos.writeObject(new Thing());
        MyObjectInputStream myObjectInputStream = new MyObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
        myObjectInputStream.readObject();
        assertEquals(-1463850548670691860L, myObjectInputStream.uid);
    }

Créé 14/01/2020 à 00:31
source utilisateur

voix
0

Votre système de couverture de test dit « personne n'accède jamais ce champ lors de vos tests unitaires ». C'est ce que le moyen de barre rouge. Donc, pour l'obtenir à partir de là, vous avez besoin d'exécuter du code qui accède à ce champ. En utilisant la réflexion pour accéder au champ pour augmenter la couverture des tests unitaires est un non-sens. Même si elle peut tourner le vert sur le terrain, ce n'est pas réellement utiliser le terrain d'une manière significative.

La bonne façon de le faire est d'exercer la classe de test d'une manière qui utilise ce champ. Le serialVersionUID est utilisé pendant la sérialisation / désérialisation pour décider si les octets qui sont en cours de lecture correspondent à l'objet que vous essayez d'instancier.

Voici un exemple simple qui couvre ce que vous voulez. J'ai ajouté un test d'égalité à la fin parce que ce vraiment ce que vous devriez tester lorsque vous êtes préoccupé par le processus sérialisation / désérialisation.

package org.does.not.exist;

import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import static org.assertj.core.api.Assertions.assertThat;

class Foo implements Serializable {
     private static final long serialVersionUID = 42L;

    public Foo(String value) {
        this.value = value;
    }

    private String value;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Foo)) return false;

        Foo foo = (Foo) o;

        return value != null ? value.equals(foo.value) : foo.value == null;
    }

    @Override
    public int hashCode() {
        return value != null ? value.hashCode() : 0;
    }
}

class StackoverflowTest {

    @Test
    void test() throws Exception {
        Foo foo = new Foo("a string!");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(foo);

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        Foo copied = (Foo) in.readObject();

        assertThat(foo).isEqualTo(copied);
    }
}

Donc, faire ce qui précède, mais remplacer Foo avec votre propre classe et vous devriez obtenir une couverture.

Créé 14/01/2020 à 01:17
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more