Home > Software design >  Mock jodd http request and response
Mock jodd http request and response

Time:03-01

I'm using Jodd http to make requests. Is there any way to create the mock so the request doesn't happen during unit tests? I've already tried to create a mock of the send() method but without success.

@Service
class ValidateUrlService {
    val TIMEOUT = 5000

    fun validateUrl(url: String): RequestVO {
        var response = HttpResponse()
        var timeBefore = Date()

        return try{
            response = HttpRequest
                .post(url)
                .timeout(TIMEOUT)
                .connectionTimeout(TIMEOUT)
                .send()

            val httpStatus = response.statusCode()

            buildResponseDTO(httpStatusToBoolean(httpStatus), httpStatus)
        } catch (ex: Exception) {
            genericExceptionHandler(ex, response.statusCode(), timeBefore)
        }
    }

My test

internal class ValidateUrlServiceTest{
    private val service = ValidateUrlService()

    @Mock
    var request: HttpRequest = HttpRequest.post(ArgumentMatchers.anyString())

    @Test
    fun test(){
        Mockito.`when`(request.send()).thenReturn(HttpResponse().statusCode(555))
        service.validateUrl("https://www.example.com")
    }

}

Error:

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(any());
verify(mock).someMethod(contains("foo"))

CodePudding user response:

Mocking only works with the injected objects. mocking doesn't work for those objects created inside the method scope

You can abstract out the HTTP calls to a different class

class HttpService {
    fun post(url: String, timeOut: Long): HttpResponse {
            return HttpRequest
            .post(url)
            .timeout(timeOut)
            .connectionTimeout(timeOut)
            .send()

    }
}

class ValidateUrlService {
    val httpService: HttpService
    val TIMEOUT = 5000

    fun validateUrl(url: String): RequestVO {
        var response = HttpResponse()
        var timeBefore = Date()

        return try{
            response = httpService.post(url, TIMEOUT)

            val httpStatus = response.statusCode()

            buildResponseDTO(httpStatusToBoolean(httpStatus), httpStatus)
        } catch (ex: Exception) {
            genericExceptionHandler(ex, response.statusCode(), timeBefore)
        }
    }

Now you should be able to mock the HttpService post method

CodePudding user response:

Your first error is here

@Mock
var request: HttpRequest = HttpRequest.post(ArgumentMatchers.anyString())

Because you are assigning to request a non mock object

If you want to use the annotations you must write you test like this: (I'm assuming that you are using JUnit5)

 @ExtendWith(MockitoExtension::class)
 internal class ValidateUrlServiceTest{
    private val service = ValidateUrlService()

    @Mock
    lateinit var request: HttpRequest

    @Test
    fun test(){
        Mockito.`when`(request.send()).thenReturn(HttpResponse().statusCode(555))
        service.validateUrl("https://www.example.com")
    }

}

The second one is that you are trying to mock an object that is created inside the method you are testing

You must provide an instance of HttpRequest through dependency injection (maybe using a provider injected as a constructor argument to ValidateUrlService)

Small tip: if you want to avoid the "ugly" syntax Mockito.`when` you can use mokito kotlin library or mockk library, both of them wrap mockito in with a more fluent kotlin way to write tests

  • Related