简体   繁体   中英

Designing Java unit test with static calls inside method

I'm trying to create a unit test for a class that has a method that uses Request.Post method from apache's fluent-hc library ( http://hc.apache.org/httpcomponents-client-ga/fluent-hc/apidocs/org/apache/http/client/fluent/Request.html ).

The thing is I don't want it to send an actual request every time I run the test suit, even less if its a unit test, not an integration one. But I don't know how to make my way around that.

I'm new in the testing world and for what I've read most of the time when you can't test something, there's a problem with the design of the class.

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;
}

}

I'm using Spring framework and Spring-Test, Mockito and TestNG as testing tools. I'll really appreciate if you could at least point me in the right direction, any material to read, book, video, anything. I just want to learn to do it the right way.

I've found some "solutions" to my problem but they all uses PowerMockito, and for what I've read is bad for you because allows mocking static methods, constructors, etc, which translate to bad coding practices, which is what I'm trying to avoid here.

For your purpose the problem is more in the apache's fluent-hc Request.Post , that is static and not mock friendly, than in your code.

You can use Executor and mock execute method, or if you want to use Request.Post wrap it in another low level service interface and use it:

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;
    }
}

That way you can easily mock the code even without mockito.

@lujop has provided a suggestion for the problem mentioned which I believe is one way to do it.

However, as to earlier statement of using mocking frameworks, I don't it is entirely a bad practice all the time. Consider the suggestion from @lujop , you would probably end up using a Test Double to unit-test RequestSenderImpl and it's business logic.

But there would be a class, say - FluentHCRequestSender - which would be responsible for actually making a call to Request.Post . Now if you were writing UTs for all your classes, you would have to use mocking framework to test FluentHCRequestSender to ensure that this class is using the right API.

There is a place for tests using mocking frameworks. But generally, it justs points to a bad design if you end up using mocking frameworks if your dependencies are classes that you, your team or your organization has created.

And to answer your question of resources that can help you in writing better UT and code in general,

SOLID principles - This is probably one thing that is always in the back of my mind while writing code.

Working Effectively with Legacy Code which has served me well.

Test Driven Development - During my practice, not very easy to strictly follow in your day-to-day routine, but it at least forces me not to put-off my UTs and work on them simultaneously with my actual classes (if not before).

Design Patterns - Grab hold of a good design pattern book/video if a library is accessible to you or buy one. The concepts might seem intimidating, but I find some of them really useful in my day-to-day work and especially while writing UTs.

But personally, the best way to learn to see existing code in your code base and see what's good and what can be improved. I have found looking and understanding code written by people who do good design much more useful than any of the books.

Hope this long winding post helps !!

PS - Kudos on trying to do the right way. Sometimes it is not said often, although it should be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM