DenisBronx / NetMock

24 stars 1 forks source link

Optional GET parameters #14

Open bartwell opened 1 month ago

bartwell commented 1 month ago

Hi, this is a very useful library, thank you.

Could you please clarify how to handle requests with optional parameters? For example, something like this: https://site.com/path?random=123. In this case, the parameter can contain a random value, and the response should be the same regardless of what the parameter contains.

I'm using the library in a KMM project with Ktor + NetMockEngine.

Thanks in advance.

DenisBronx commented 1 month ago

Hi @bartwell , thanks for using NetMock!

When unit testing, it's important to verify that requests are made with the correct parameters. Ignoring query parameters in your tests can lead to a situation where production code breaks, but all tests still pass. This is why NetMock requires that you specify the request parameters exactly as they will be used.

For your scenario, I recommend gaining control over the random parameter in your tests. For example, you can use an approach like this:

interface RandomGenerator {
    fun generateRandom(): Int
}

class MyClassTest {
    private val netMock = NetMockEngine()
    private val httpClient = HttpClient(netMock) {
        install(ContentNegotiation) {
            json()
        }
    }
    private val randomGenerator = object : RandomGenerator {
        override fun generateRandom(): Int {
            return RANDOM_NUMBER
        }
    }
    private val sut = MyClass(httpClient, randomGenerator)

    @Test
    fun `EXPECT success response`() = runTest {
        netMock.addMock(
            request = {
                requestUrl = "https://site.com/path?random=$RANDOM_NUMBER"
                method = Method.Get
            },
            response = {
                code = 200
            }
        )

        val result = sut.doSomething()

        assertTrue(result)
    }

    private companion object {
        val RANDOM_NUMBER = Random.nextInt()
    }
}

class MyClass(
    private val httpClient: HttpClient,
    private val randomGenerator: RandomGenerator
) {
    suspend fun doSomething(): Boolean {
        val response = httpClient.get(
            "https://site.com/path?random=${randomGenerator.generateRandom()}"
        )
        return response.status.isSuccess()
    }
}

Alternatively, you can set a default NetMock response and verify only the request details that matter to you afterward:

@Test
fun `EXPECT success response using default response`() = runTest {
    netMock.defaultResponse = NetMockResponse(code = 200)

    val result = sut.doSomething()

    assertTrue(result)
    val interceptedRequest = netMock.interceptedRequests[0]
    assertTrue(interceptedRequest.requestUrl.contains("https://site.com/path?random="))
    assertEquals(Method.Get, interceptedRequest.method)
}

However, I would discourage this approach as it doesn't fully test the request logic.