Mockito: вызов метода внутри метода - PullRequest
2 голосов
/ 25 декабря 2011

У меня есть следующий класс и метод внутри него

public class A extends B implements C{


public void validateTicketGrantingTicket(final TicketGrantingTicket ticketGrantingTicket) throws InvalidTicketException {

    if (ticketGrantingTicket != null)
    {
        if (!ticketGrantingTicket.getHostDomain().equalsIgnoreCase(getServerName()))
        {
            throw new InvalidTicketException();
        }
    }
}


public String getServerName()
{
    String serverName = "";
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

    if (request != null)
    {
        serverName = request.getServerName().toLowerCase();
    }

    return serverName;
}
}

Теперь я пишу класс ATest и класс mocking A.

public class ATest {
private A a;

@Before
public void init(){

    A = mock(A.class);

    when(A.getServerName()).thenReturn("phoenix.edu.abc");      
}


@Test
public void validateTicketGrantingTicketTest() throws  InvalidTicketException{  
    a = new A();
    ticketGrantingTicket = new   
    TicketGrantingTicketImpl("test",testUtils.getAuthentication(), new 
    NeverExpiresExpirationPolicy());

    a.validateTicketGrantingTicket(ticketGrantingTicket);
}

Mock объект дает мне исключение нулевого указателя для getServerName() вместо строки "phoenix.edu.abc"

Ответы [ 2 ]

7 голосов
/ 25 декабря 2011

Вызывая a = new A(); в своем методе тестирования, вы создаете новый экземпляр A, и ссылка на ложный экземпляр A, созданный в методе init(), будет потеряна.Следовательно, будет вызвана «реальная» реализация A метода getServerName(), а не того, над которым вы издевались.

Другая проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь одновременно и макетировать, и тестировать один и тот же класс.С одной стороны, вы тестируете validateTicketGrantingTicket(), но в то же время вы издеваетесь getServerName().Вы можете обойти эту проблему, используя spy () вместо mock(), но лучше реорганизовать код в два отдельных класса.

0 голосов
/ 26 декабря 2011

Полагаю, не стоит переместить метод getServerName в другой класс, чтобы его можно было использовать в другом месте?Это позволит легко протестировать этот сценарий.

Как сказал Мацев, вы также пытаетесь издеваться над тестируемым классом, что является неправильной практикой.Это может быть использовано в исключительных ситуациях, как он указал, используя spy().Даже mockito представил эту функцию в своих более поздних выпусках, но настоятельно рекомендует пользователям ограничить использование spy().

Если вы переместите метод в новый класс, вы можете легко смоделировать другой класс и вернуть значениечто вам нужно.

public class A extends B implements C{
private AUtil util;

public void validateTicketGrantingTicket(final TicketGrantingTicket ticketGrantingTicket) throws InvalidTicketException {

    if (ticketGrantingTicket != null)
    {
        String serverName = util.getServerName()
        if (!ticketGrantingTicket.getHostDomain().equalsIgnoreCase(serverName))
        {
            throw new InvalidTicketException();
        }
    }
}
}


public class AUtil {
public String getServerName()
{
    String serverName = "";
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

    if (request != null)
    {
        serverName = request.getServerName().toLowerCase();
    }

    return serverName;
}
}

Теперь это можно считать хорошим дизайном, если мы переместим все вспомогательные функции в общий класс, из которого все классы, такие как A, могут использовать их повторно.Теперь у него отдельная забота и лучшая тестируемость.Вы можете легко издеваться над этим методом без шпиона.

public class ATest {

//cut provides a uniform naming convention-Class Under Test
private AUtil cut;

//Mock can now be created using annotations in Mockito
@Mock
AUtil mock;

@Test
public void validateTicketGrantingTicketTest() throws  InvalidTicketException{  

    cut = new A();

    ticketGrantingTicket = new   
    TicketGrantingTicketImpl("test",testUtils.getAuthentication(), new 
    NeverExpiresExpirationPolicy());

    when(mock.getServerName()).thenReturn("phoenix.edu.abc");

    a.validateTicketGrantingTicket(ticketGrantingTicket);
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...