我正在尝试为一个类创建一个单元测试,该类的方法使用来自apache的fluent-hc库(http://hc.apache.org/httpcomponents-client-ga/fluent-hc/apidocs/org/apache/http/client/fluent/Request.html)的Request.Post方法。
问题是我不希望每次运行测试时都发送实际请求,如果是单元测试,则更少,而不是集成测试。但我不知道如何绕过那条路。
我是测试世界的新手,而且在大多数时候,当你无法测试某些东西时,我读到的是这个类的设计存在问题。
public class HttpRequestSenderServiceImpl implements RequestSenderService {
@Override
public Response sendRequest(String address, String messageBody) throws IOException {
Request request = Request.Post(address).bodyString(messageBody, ContentType.APPLICATION_JSON);
Response response = request.execute();
return response;
}
}
我使用Spring框架和Spring-Test,Mockito和TestNG作为测试工具。如果你能指出我正确的方向,任何阅读材料,书籍,视频,任何东西,我将非常感激。我只想学习正确的方法。
我找到了一些问题的“解决方案”,但它们都使用了PowerMockito,而我读过的内容对你有害,因为它允许模拟静态方法,构造函数等,这会导致错误的编码实践,这就是我所说的我试图避免在这里。
为了你的目的,问题更多的是在apache的fluent-hc Request.Post
中,这是静态的,而不是模拟友好的,而不是你的代码。
您可以使用Executor和模拟执行方法,或者如果您想使用Request.Post
将其包装在另一个低级服务接口中并使用它:
interface RequestSender {
Response send(String addr,msgBody)
}
class RequestSenderImpl implements RequestSender {
public Response send(String addr,msgBody) {
Request request = Request.Post(address).bodyString(messageBody,ContentType.APPLICATION_JSON);
Response response = request.execute();
return response;
}
}
这样,即使没有mockito,您也可以轻松地模拟代码。
@lujop对提到的问题提出了一个建议,我认为这是一种方法。
但是,关于使用模拟框架的早期声明,我并不是一直都是不好的做法。考虑一下@lujop的建议,您最终可能会使用Test Double对RequestSenderImpl进行单元测试及其业务逻辑。
但是会有一个班级,比如说 - FluentHCRequestSender
--负责实际打电话给Request.Post
。现在,如果您为所有类编写UT,则必须使用模拟框架来测试FluentHCRequestSender
以确保此类使用正确的API。
有一个使用模拟框架进行测试的地方。但一般来说,如果您的依赖项是您,您的团队或您的组织创建的类,那么如果最终使用模拟框架,那么它只会指向糟糕的设计。
并回答您的资源问题,可以帮助您编写更好的UT和代码,
SOLID principles - 在编写代码时,这可能是我脑海中的一件事。
Working Effectively with Legacy Code一直很好。
Test Driven Development - 在我练习期间,在你的日常工作中并不是很容易严格遵守,但它至少迫使我不要推迟我的UT并与我的实际课程同时工作(如果不是之前)。
Design Patterns - 如果您可以访问图书馆或购买图书馆,请抓住好的设计图书/视频。这些概念可能看起来令人生畏,但我发现其中一些在我的日常工作中非常有用,特别是在编写UT时。
但就个人而言,这是学习在代码库中查看现有代码并了解哪些代码有用以及哪些内容可以改进的最佳方式。我发现查找和理解由设计好的设计的人编写的代码比任何书籍都更有用。
希望这篇长篇大论有助于!!
PS - 努力做正确的方法。虽然应该这样,但有时并不常说。