Método Mockito repetitiva de llamadas en la misma Funciton / Constructor se está probando

Cerberus en frío:

Aquí está la clase Person

public class Person {
    // ...
    public String getInfo(String key)
            return key; //for brevity
    }
}

Y otra clase Studentque tiene una dependencia en Person(Tenga en cuenta que la implementación actual es parte del problema y no podemos modificar estas dos clases)

public class Student {
    private String copyFirstName;
    private String otherInfo;

    private Person person;
    Student(Person p) {
        person = p;

        copyFirstName = person.getInfo("firstName")

        if (copyFirstName == null || copyFirstName.equals("")) { //entry point A
            throw new SomethingError("message here");
        }

        otherInfo = person.getInfo("bio")

        if (otherInfo == null || otherInfo.equals("")) { // entry point B
            throw new SomethingError("message here");
        }
    }
}

Las clases anterior pueden ser poco práctico, pero tomarlo como parte del problema que no podemos cambiar.

El objetivo es tener una cobertura completa de todas las líneas en las pruebas. Para ello, tengo la intención de hacer dos pruebas para cubrir los dos ifestados y un prototipo del método getInfoaunque toma nota de lo que se pasa el parámetro para que yo sepa cuándo debe omitir el "punto de entrada A" para la segunda prueba del constructor.

Lo ideal sería que esta sería mi clase JUnit

public class StudentTest {
    private Person person;
    private Student student;
    private Person mockedPerson;

    @Before
    public void init()
    throws SomethingError  {
        person = new Person();
        student = new Student();
        mockedPerson = Mockito.mock(Person.class);
    }

    @Test(expected=SomethingError.class)
    public void myTest1()
    throws SomethingError {
        Mockito.when(mockedPerson.getInfo("firstName"))
        .thenAnswer(
            new Answer<String>(){
            @Override
            public String answer(InvocationOnMock invocation) {
                String arg = invocation.getArgumentAt(0, String.class);
                System.out.println(arg);
                if (arg.equals("firstName")) {
                    return null;
                }
                return person.getInfo(arg); // default value
            }});

        try {
            new Student(mockedPerson);
            fail();
        } catch (MultilingualException e) {
            Mockito.reset(mockedPerson); // not sure if this works
            assertEquals(e.getMessage(), "message here");
        }
    }

    @Test(expected=SomethingError.class)
    public void myTest2()
    throws SomethingError {
        Mockito.when(mockedPerson.getInfo("bio"))
        .thenAnswer(
            new Answer<String>(){
            @Override
            public String answer(InvocationOnMock invocation) {
                String arg = invocation.getArgumentAt(0, String.class);
                System.out.println(arg);
                if (arg.equals("bio")) {
                    return "";
                }
                return person.getInfo(arg); // defaul value for firstName
            }});

        try {
            new Student(mockedPerson);
            fail();
        } catch (MultilingualException e) {
            Mockito.reset(mockedPerson); // not sure if this works
            assertEquals(e.getMessage(), "message here");
        }
    }
}

Pero no funciona como se esperaba. myTest1entrado con éxito en el primer ifcomunicado. Pero entonces myTest2, la segunda ifafirmación es olvidada. Extrañamente todo por debajo de @ Override myTest2se pierde y pasa inmediatamente a su catch.

También he intentado crear instancia burlado individual de Person, pero todavía tiene un resultado idéntico cobertura.

¿Cómo se podría probar y cubrir las dos consecutivos ifdeclaraciones en el constructor que obtiene el valor evaluado del mismo método?

Editar

Yo probé el método más simple de abajo, pero parece que .whenno se preocupa de lo que el valor del argumento es desde la segunda prueba sigue activa la primera if.

@Test(expected=SomethingError.class)
public void test() throws SomethingError {
    Mockito.when(mockedPerson.getInfo("firstName")).thenReturn(null);
    try {
        new Student(mockedPerson);
    } catch (SomethingError e) {
        assertEquals(e.getMessage(), "message here");
    }
}

@Test(expected=SomethingError.class)
public void test2() throws SomethingError {
    Mockito.when(mockedPerson.getInfo("bio")).thenReturn(null);
    try {
        new Student(mockedPerson);
    } catch (SomethingError e) {
        assertEquals(e.getMessage(), "message here");
    }
}
A4L:

No hay necesidad de eso private Student student;, podía comprender que puede deshacerse de todos los campos de la clase de prueba, las pruebas deberán ser llenados tan independiente como sea posible y, en su caso, usted podría hacer la burla y Stubing alltoghether en cada método de ensayo. Utilizar

ArgumentMatchers.eq("firstName");

examinarlo valor del argumento de la igualdad, también puede utilizar la variante de respuesta si lo desea, pero en caso de que esto que es mucho más simple.

Aquí es cómo sus pruebas podrían ser:

@Test
public void newStudentWithPersonWithNullFirstName() {

    Person person = Mockito.mock(Person.class);

    Mockito
        .doReturn(null)
        .when(person)
        .getInfo(ArgumentMatchers.eq("firstName"));

    SomethingError actual = Assert
            .assertThrows(SomethingError.class, () -> new Student(person));
    Assert.assertEquals("firstName is null or empty", actual.getMessage());
}

@Test
public void newStudentWithPersonWithEmptyFirstName() {

    Person person = Mockito.mock(Person.class);

    Mockito
        .doReturn("")
        .when(person)
        .getInfo(ArgumentMatchers.eq("firstName"));

    SomethingError actual = Assert
            .assertThrows(SomethingError.class, () -> new Student(person));
    Assert.assertEquals("firstName is null or empty", actual.getMessage());
}

@Test
public void newStudentWithPersonWithNullBio() {

    Person person = Mockito.mock(Person.class);

    Mockito
        .doReturn("Foo")
        .when(person)
        .getInfo(ArgumentMatchers.eq("firstName"));

    Mockito
        .doReturn(null)
        .when(person)
        .getInfo(ArgumentMatchers.eq("bio"));

    SomethingError actual = Assert
            .assertThrows(SomethingError.class, () -> new Student(person));
    Assert.assertEquals("bio is null or empty", actual.getMessage());
}

@Test
public void newStudentWithPersonWithEmptyBio() {

    Person person = Mockito.mock(Person.class);

    Mockito
        .doReturn("Foo")
        .when(person)
        .getInfo(ArgumentMatchers.eq("firstName"));

    Mockito
        .doReturn("")
        .when(person)
        .getInfo(ArgumentMatchers.eq("bio"));

    SomethingError actual = Assert
            .assertThrows(SomethingError.class, () -> new Student(person));
    Assert.assertEquals("bio is null or empty", actual.getMessage());
}

@Test
public void newStudentWithPersonSuccess() {

    Person person = Mockito.mock(Person.class);

    Mockito
        .doReturn("Foo")
        .when(person)
        .getInfo(ArgumentMatchers.eq("firstName"));

    Mockito
        .doReturn("Bar")
        .when(person)
        .getInfo(ArgumentMatchers.eq("bio"));

    Student actual = new Student(person);
    Assert.assertEquals("Foo", actual.getCopyFirstName());
    Assert.assertEquals("Bar", actual.getOtherInfo());
}

Cobertura:

introducir descripción de la imagen aquí

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=371042&siteId=1
Recomendado
Clasificación