如何为单元测试模拟HttpClientBuilder

时间:2019-09-17 23:33:48

标签: java unit-testing http mockito

我正在尝试为http post实现编写单元测试。但是,我无法正确模拟httpclient,并且永远不会触发我的when语句。我编写的单元测试是进行实际的http调用,而不是通过模拟响应进行响应。 我们如何继续模拟由HttpClientBuilder创建的客户端?

Http方法实现:

HttpResponse postRequest(String url, String request) {
    HttpResponse resp = null;
    try {
        HttpClient client = HttpClientBuilder.create().useSystemProperties().build();
        HttpPost post = new HttpPost(url);
        post.addHeader("Content-Type", "application/x-www-form-urlencoded");
        post.setEntity(new StringEntity(request));

        resp = client.execute(post);
    } catch (Exception e) {
        return null;
    }
}

测试方法:

@Mock
private HttpClient httpClient;

when(httpClient.execute(any())).thenReturn(httpResponse);

1 个答案:

答案 0 :(得分:1)

  

我们如何继续模拟由HttpClientBuilder创建的客户端?

我们不!

尽量避免嘲笑第三者的担忧

创建紧密耦合的静态实现关注点的抽象

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: <Widget>[
          Wrap(
            spacing: 4.0,
            children: <Widget>[
              for (var i = 0; i < 30; i++)
                ChoiceChip(
                  label: Text("item $i"),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(30.0),
                  ),
                  backgroundColor: Color(0xffededed),
                  selectedColor: Color(0xffffc107),
                  selected: false,
                  onSelected: (b) {},
                )
            ],
          ),
        ],
      ),
    );
  }
}

具有将在生产中使用的简单实现。

public interface HttpClientFactory {
    public HttpClient create();
}

使用依赖倒置,封装类应显式依赖于抽象,以避免违反单一职责原则(SRP)

public class HttpClientFactoryImpl implements HttpClientFactory {

    //...

    public HttpClient create() {
        return HttpClientBuilder.create().useSystemProperties().build();
    }

    //...
}

此关注分离(SoC)允许(您的封装类)更加灵活地进行隔离的单元测试。

public class SystemUnderTest {

    private HttpClientFactory httpClientFactory;

    public SystemUnderTest(HttpClientFactory httpClientFactory) {
        this.httpClientFactory = httpClientFactory;
    }

    HttpResponse postRequest(String url, String request) {
        HttpResponse resp = null;
        try {
            HttpClient client = httpClientFactory.create();
            HttpPost post = new HttpPost(url);
            post.addHeader("Content-Type", "application/x-www-form-urlencoded");
            post.setEntity(new StringEntity(request));

            resp = client.execute(post);
            return resp;
        } catch (Exception e) {
            return null;
        }
    }
}