mock https request in java

2020-07-11 08:19发布

Let's say I'm writing an application and I need to be able to do something like this:

String url = "https://someurl/";
GetMethod method = new GetMethod(URLEncoder.encode(url));
String content = method.getResponseBodyAsString();

Is there a way to provide a mock server that would let me handle the https request? What I'm looking for is a way to write unit tests, but I need to be able to mock the part that actually goes out to https://someurl so I can get a known response back.

8条回答
混吃等死
2楼-- · 2020-07-11 08:41

If you are writing a unit test, you dont want any external dependencies. from the api,

GetMethod 

extends

HttpMethod

so you can easily mock it with your favorite mocking library. Your

method.getResponseBodyAsString()

call can be mocked to return any data you want.

查看更多
欢心
3楼-- · 2020-07-11 08:41

You can wrap that code in some class and have WebClient.getUrl() and then mock (e.g. jmock) that method to return stored files - say

expectation {
   oneOf("https://someurl/"), will(returnValue(someHTML));
}
查看更多
霸刀☆藐视天下
4楼-- · 2020-07-11 08:43

You essentially have two options:

1. Abstract the call to the framework and test this.

E.g. refactor the code to allow you to inject a mock implementation at some point. There are many ways to do this. e.g. create a getUrlAsString() and mock that. (also suggested above). Or create a url getter factory that returns a GetMethod object. The factory then can be mocked.

2. Start up a app server as part of the test and then run your method against it. (This will be more of an integration test)

This can be achieved in an number of ways. This can be external to the test e.g. the maven jetty plugin. or the test can programmatically start up the server. see: http://docs.codehaus.org/display/JETTY/Embedding+Jetty

Running it over https will complicate this but it will still be possible with self signed certs. But I'd ask yourself - what exactly you want to test? I doubt you actually need to test https functionality, its a proven technology.

Personally I'd go for option 1 - you are attempting to test functionality of an external library. That is usually unnecessary. Also it's good practice to abstract out your dependencies to external libraries.

Hope this helps.

查看更多
太酷不给撩
5楼-- · 2020-07-11 08:45

To what extend are you interested in mocking this "Get" call, because if you are looking for a general purpose mocking framework for Java which integrates well with JUnit and allows to setup expectations which are automatically asserted when incorporated into a JUnit suite, then you really ought to take a look at jMock.

Now without more code, it's hard to determine whether this is actually what you are looking for, but a (somewhat useless) example, of something similar to the example code you wrote, would go something like this:

class GetMethodTest {
@Rule public JUnitRuleMockery context = new JunitRuleMockery();

@Test
public void testGetMethod() throws Exception {
    // Setup mocked object with expectations
    final GetMethod method = context.mock(GetMethod.class);
    context.checking(new Expectations() {{
        oneOf (method).getResponseBodyAsString();
        will(returnValue("Response text goes here"));
    }});

    // Now do the checking against mocked object
    String content = method.getResponseBodyAsString();
}
}
查看更多
萌系小妹纸
6楼-- · 2020-07-11 08:46

Take a look at jadler (http://jadler.net), an http stubbing/mocking library I've been working on for some time. The 1.0.0 stable version has been just released, it should provide the capabilities you requested:

@Test
public void getAccount() {

    onRequest()
        .havingMethodEqualTo("GET")
        .havingURIEqualTo("/accounts/1")
        .havingBody(isEmptyOrNullString())
        .havingHeaderEqualTo("Accept", "application/json")
    .respond()
        .withTimeout(2, SECONDS)
        .withStatus(200)
        .withBody("{\"account\":{\"id\" : 1}}")
        .withEncoding(Charset.forName("UTF-8"))
        .withContentType("application/json; charset=UTF-8");

    final AccountService service = new AccountServiceRestImpl("http", "localhost", port());
    final Account account = service.getAccount(1);

    assertThat(account, is(notNullValue()));
    assertThat(account.getId(), is(1));
}


@Test
public void deleteAccount() {

    onRequest()
        .havingMethodEqualTo("DELETE")
        .havingPathEqualTo("/accounts/1")
    .respond()
        .withStatus(204);

    final AccountService service = new AccountServiceRestImpl("http", "localhost", port());
    service.deleteAccount(1);

    verifyThatRequest()
        .havingMethodEqualTo("DELETE")
        .havingPathEqualTo("/accounts/1")
    .receivedOnce();
}
查看更多
贼婆χ
7楼-- · 2020-07-11 08:46

Take a look at JWebUnit http://jwebunit.sourceforge.net/

Here is an example of a test...Its really quite intuitive.

public class ExampleWebTestCase extends WebTestCase {
    public void setUp() {
        super.setUp();
        setBaseUrl("http://localhost:8080/test");
    }

    public void test1() {
        beginAt("/home");
        clickLink("login");
        assertTitleEquals("Login");
        setTextField("username", "test");
        setTextField("password", "test123");
        submit();
        assertTitleEquals("Welcome, test!");
    }
}
查看更多
登录 后发表回答