Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on How to unittest method that involves contacting remote servers?

Post

How to unittest method that involves contacting remote servers?

+6
−1

Let's say I have this class:

class myService {
    private boolean foo(T arg) { return arg == 42; }

    public Response bar(U arg) {
        if(foo(U.field)) {
            return Response.status(Response.Status.BAD_REQUEST).build();
        }

        // Code that contacts a remote server
    }
}

I want to unittest this with Junit. But there are some problems. I'm actually mainly interested in testing foo(), but that one is private. I could make it public, but I really don't want to do that just so that the test class can access it. I could also write a wrapper around bar() but again, it feels weird to modify the API for this purpose.

It works fine to test test cases that should fail, which in this case means that foo returns true. But in the case that foo returns false, we will reach the code that contacts remote servers, and that's not desirable.

How should I refactor this so that I can test foo via bar regardless if foo returns true or false?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

1 comment thread

DI? (5 comments)
DI?
elgonzo‭ wrote over 2 years ago · edited over 2 years ago

The question you have to answer yourself is: What do you really want to test here? Do you actually want to test the behavior of the server? If so, why are you trying to test foo? Or do you rather want -- as your question states -- to test the behavior of your code? If that's the case, why would you want the headache of an external system (and possibly a changing configuration of server or network infrastructure) potentially screwing up your test runs?

I mean, instead of "just" having to worry about the correctness of your tests, you would now have to worry about the correctness of your tests and the correct behavior of the server. I don't know, but that doesn't sound like fun... :-)

elgonzo‭ wrote over 2 years ago · edited over 2 years ago

Relocate your server-related I/O into its own service with an API defined through an interface or such. Then use dependency injection (either through a parameterized constructor or through some service provider thingamabob; sorry, i am not a Java programmer, so i don't know typical/popular Java DI frameworks) to inject this service/class into myService.

Then, for the unit tests, that service could be mocked/stubbed, backed by a test-specific implementation that simulates the required and well-defined server behavior the test is intended to run against (without actually relying on any server).

klutt‭ wrote over 2 years ago

elgonzo‭ Yes, you're completely right. I'm looking for a mocking solution now. However, I would still like to be able to test this separately. Mainly because some tests will go very quick to run, and can be executed as part of the build process. But other tests will be to much of a slowdown.

elgonzo‭ wrote over 2 years ago · edited over 2 years ago

What exactly do you mean with "test this separately"? If the intention is to just test the private function foo in isolation and independently from bar, you might want to check whether some of the suggestions given here might work for you: https://softwareengineering.stackexchange.com/questions/100959/how-do-you-unit-test-private-methods (Again, i am not Java programmer, so i can't give any meaningful comment about those suggestions)

klutt‭ wrote over 2 years ago · edited over 2 years ago

elgonzo‭ Yes, I actually saw that.

I agree with what they say in the accepted answer. That private methods should be considered implementation details in general. But reality does not follow the books unfortunately. In my case, foo has a very simple, yet very distinct task. It's job is to validate the input to bar. So it really makes sense to test it separately.