Модульное тестирование Java путем создания фиктивного объекта интерфейса, который выполняет некоторую работу - PullRequest
0 голосов
/ 06 сентября 2011

Я не уверен, как сказать, что я хочу сделать, поэтому заранее прошу прощения

В настоящее время я пишу модульные тесты для некоторого устаревшего кода как часть моей работы.Одним из этих кусочков кода является (Java) HttpServlet, который предоставляет URL перенаправления.По сути код выглядит следующим образом:

public class Server extends HttpServlet {
  ...
  public void doGet(HttpServletRequest request, HttpServletResponse response) {
    ...
    String url = "....";
    .. // do some work to create that url
    response.sendRedirect(url);
  }
  ...
}

В рамках моего модульного теста для этого класса я хочу проверить созданный URL-адрес перенаправления.Поэтому я хотел бы сделать что-то вроде:

 Server server = new Server();
 ..
 server.doGet(request, response);
 String url = getRedirectURL(response);
 // test URL returned
 ...

Каков наилучший способ 'getRedirectURL' из ответа?

В настоящее время я использую Junit и Jmock (обе последние версии).Я создаю Mock HttpServletRequest и могу легко создать фиктивный HttpServletResponse и добавить ожидание для метода sendRedirect (url), ЕСЛИ я знал ожидаемый формат URL, однако я не знаю.

Моя попытка была создатьфиктивный класс, реализующий HttpServletResponse, который сохранил значение URL, а затем позволил мне получить его позже.то есть

  private class MockHttpServletResponse implements HttpServletResponse {
  String url;
  public String getURL() {
     return url;
  }
  public void sendRedirect(String url) {
     this.url = url;
  }
 }

Однако, поскольку он реализует интерфейс, Java хочет, чтобы я реализовал ВСЕ методы в HttpServletResponse, которые я действительно не хочу делать.

Заранее спасибо :) iпопробую и перефразирую это

Ответы [ 3 ]

1 голос
/ 07 сентября 2011

Вам необходимо реализовать пользовательское сопоставление.См. Написание новых сопоставителей

Настраиваемое сопоставление позволяет вам тестировать именно то, что вы хотите, но также позволяет сохранять значение, которое передается сопоставителю, чтобы вы могли получитьпозже:

С сайта jmock:

import org.hamcrest.AbstractMatcher;

public class StringStartsWithMatcher extends TypeSafeMatcher<String> {
    private String prefix;
    private String calledValue; // ADDED THIS

    public StringStartsWithMatcher(String prefix) {
        this.prefix = prefix;
    }

    public String getCalledValue() {
        return calledValue;
    }

    public boolean matchesSafely(String s) {
        this.calledValue = s; // AND HERE
        return s.startsWith(prefix);
    }

    public StringBuffer describeTo(Description description) {
        return description.appendText("a string starting with ").appendValue(prefix);
    }
}

@Factory
public static Matcher<String> aStringStartingWith( String prefix ) {
    return new StringStartsWithMatcher(prefix);
}

public class MyTestCase {
    ...

    public void testSomething() {
        ...

        TypeSafeMatcher<String> matcher = aStringStartingWith("http")

        context.checking(new Expectations() {{
            oneOf (logger).error(with(matcher));
        }});

        // more tests using matcher.getCalledValue()
        ...
    }
}

Таким образом, вы сохраняете значение url в namedValue, которое затем извлекаете через getCalledValue ().

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

Учитывая, что все это происходит в модульном тесте, не можете ли вы предсказать, каким будет URL-адрес, и сопоставить его?Тем не менее, часто стоит использовать средства сравнения, чтобы выделить только те функции, которые вам нужны, что делает тест более сфокусированным.

0 голосов
/ 06 сентября 2011

Полагаю, вы просто хотите подтвердить, что метод sendRedirect был вызван в макете ответа, но вам все равно, какое значение было. Если это так, вы можете установить ожидание так:

response.sendRedirect(with(a(String.class)));
...