【问题标题】:OkHttp MockWebServer fails to accept connections when restartedOkHttp MockWebServer 重新启动时无法接受连接
【发布时间】:2016-10-24 05:59:14
【问题描述】:

我正在使用OkHttp MockWebServer 模拟我的服务器响应以进行单元测试。

第一次测试效果很好,但在第二次测试中我的客户失败了:

无法连接到 localhost/0:0:0:0:0:0:0:1:63631

即使第二次测试与第一次完全相同,也会发生这种情况。
这就是我正在做的事情:

@RunWith(RobolectricTestRunner.class)
@Config(shadows = MyClassTest.MyNetworkSecurityPolicy.class,
        manifest = "src/main/AndroidManifest.xml",
        constants = BuildConfig.class,
        sdk = 16)
public class MyClassTest {
    private MockWebServer mockServer;
    private MyServerApi serverApi;

    @Before
    public void setUp() throws Exception {
        System.out.println("\ntest start");
        this.mockServer = new MockWebServer();
        this.mockServer.start();

        this.serverApi = new MyServerApi(this.mockServer.url("/").toString());
    }

    @Test
    public void testOne() throws Exception {
        final String responseBody = // read response from file
        this.mockServer.enqueue(new MockResponse().setResponseCode(200).setBody(responseBody));

        final Waiter waiter = new Waiter();
        this.serverApi.getData("some_id", new Callback<MyResponseData> {
            @Override
            public void onResponse(final Call<MyResponseData> call, final Response<MyResponseData> response) {
                waiter.assertEquals("some_value", response.body().getValue());
                waiter.resume();
            }

            @Override
            public void onFailure(final Call<T> call, final Throwable error) {
                waiter.fail(error);
            }
        });

        waiter.await();

        final RecordedRequest recordedRequest = this.mockServer.takeRequest();
        assertEquals("GET", recordedRequest.getMethod());
    }

    @Test
    public void testTwo() throws Exception {
        final String responseBody = // read response from file
        this.mockServer.enqueue(new MockResponse().setResponseCode(200).setBody(responseBody));

        final Waiter waiter = new Waiter();
        this.serverApi.getData("some_id", new Callback<MyResponseData> {
            @Override
            public void onResponse(final Call<MyResponseData> call, final Response<MyResponseData> response) {
                waiter.assertEquals("some_value", response.body().getValue());
                waiter.resume();
            }

            @Override
            public void onFailure(final Call<T> call, final Throwable error) {
                waiter.fail(error);
            }
        });

        waiter.await();

        final RecordedRequest recordedRequest = this.mockServer.takeRequest();
        assertEquals("GET", recordedRequest.getMethod());
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("test end\n");
        this.mockServer.shutdown();
    }

    @Implements(NetworkSecurityPolicy.class)
    public static class MyNetworkSecurityPolicy {
        @Implementation
        public static NetworkSecurityPolicy getInstance() {
            try {
                Class<?> shadow = MyNetworkSecurityPolicy.class.forName("android.security.NetworkSecurityPolicy");
                return (NetworkSecurityPolicy) shadow.newInstance();
            } catch (Exception e) {
                throw new AssertionError();
            }
        }

        @Implementation
        public boolean isCleartextTrafficPermitted() {
            return true;
        }
    }
}

第一个测试按原样通过,但第二个测试失败并显示我上面写的消息。
控制台的输出是:

test start
okhttp3.mockwebserver.MockWebServer$3 execute
INFO: MockWebServer[63631] starting to accept connections
WARNING: no system properties value for gsm.sim.operator.alpha
okhttp3.mockwebserver.MockWebServer$4 processOneRequest
INFO: MockWebServer[63631] received request: GET REQUEST_PATH HTTP/1.1 and responded: HTTP/1.1 200 OK
okhttp3.mockwebserver.MockWebServer$3 acceptConnections
test end

INFO: MockWebServer[63631] done accepting connections: Socket closed

test start
okhttp3.mockwebserver.MockWebServer$3 execute
INFO: MockWebServer[63649] starting to accept connections
okhttp3.mockwebserver.MockWebServer$3 acceptConnections
INFO: MockWebServer[63649] done accepting connections: Socket closed
on error: Failed to connect to localhost/0:0:0:0:0:0:0:1:63631
test end

Waiter 对象的东西来自concurrentunit lib

知道为什么会这样吗?

【问题讨论】:

  • 你是如何解决这个问题的,我在同一个类中也有两个方法来测试 API 的有效和无效响应,当我单独运行它时,两个测试方法都可以正常工作。但是当我运行整个班级时,其中一个工作,另一个给出Failed to connect to localhost/127.0.0.1:58688 错误。您是如何解决这个问题的?
  • @Kavita_p 我不记得了,3 年多了。我将一个答案标记为已接受,所以我猜这个答案有所帮助。
  • 嗨@Nitzan Tomer,我通过将mockWebServer.start(PORT_NUMBER) 常量端口号设置为我的mockWebServer 解决了上述问题,并且我在@After method 中使用mockWebServer.shutdown() 在完成测试后将其关闭案例
  • 我通过保持不变的端口号解决了同样的问题。由于不提供恒定端口号可能会在随机端口上启动新的模拟 Web 服务器,因此我们在 android 中的改造实例(或您用于 HTTP 请求的任何内容)无法在第一个模拟服务器使用的端口上发送请求,因为我们用来获取基本 url 的内容。

标签: java android unit-testing okhttp mockwebserver


【解决方案1】:

您的第二个请求正在使用第一个 MockWebServer 实例的 URL。 (每个实例都有一个不同的 URL。)

【讨论】:

  • 有趣,但我不明白这是怎么回事。据我了解,setUp 方法发生在每个测试方法之前,这意味着创建了一个新的模拟服务器实例,并创建了我的服务器 api 的一个新实例以及新创建的模拟服务器的 url。还是我在这里遗漏了什么?
  • 好吧,事实证明你是对的。在我发布的示例中不应该是这种情况,因为它是一个简单的示例,但是在我的实际代码中,我将第一个模拟服务器的地址缓存在我的服务器 api 实例中。谢谢!
  • @JesseWilson @Jesse Wilson,我遇到了同样的问题。我在同一个类中也有两种方法来测试 API 有效和无效响应,当我单独运行它时,两种测试方法都可以正常工作。但是当我运行整个课程时,其中一个可以工作,另一个给出 Failed to connect to localhost/127.0.0.1:58688 错误。而如果我检查端口号mockWebServer.getPort(),它会提供两个不同的端口。我应该如何处理这个问题?提前致谢。
【解决方案2】:

此本地主机连接失败,因为它不属于模拟服务器。改用这个 (mockHelper.getHost()).willReturn(okhttpMockWebServer.url("/").toString())

【讨论】:

  • 请对您的回答进行解释,例如:什么对象是 mockhelper。
猜你喜欢
  • 1970-01-01
  • 2019-10-19
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
相关资源
最近更新 更多