0

After searching around the net for few days, couldn't really find the resources I need for my use case as many of it are implemented in Java.

I have a service class that is calling external api, and I am trying to write unit tests on it with MockWebServer

@Service
class ApiService {
    @Autowired
    private lateinit var webClient: WebClient

    fun getApiResult(name: String): ResultDto? {
        return try {
           webClient
               .get()
               .uri("https://www.example.com/")
               .retrieve()
               .bodyToMono(Result::class)
               .block()
            catch {
               null
        }
    }
}
@ExtendWith(MockitoExtension::class)
@MockitoSettings(strictname = Strictness.LENIENT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ApiServiceTest {
    @Mock
    private lateinit var webClient: WebClient

    @InjectMocks
    private lateinit var mockApiService: ApiService

    private val mockName = "mockName"
    private val mockDetailDto = DetailDto(name = "mockName", age = 18)

    @Test
    fun canGetDetails() {
        mockWebServer.enqueue(
            MockResponse()
                .setResponse(200)
                .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .setBody(mockDetailDto))
        )

        mockApiService.getApiResult(mockName)
        val request: RecordedRequest = mockWebServer.takeRequest()

        // Assert statements with request
    }
}

However, I am getting lateinit property webClient has not been initialised. But if I were to use @Spy instead of @Mock for the webClient in my test, it will be making actual apis calls which is not the goal of unit test. My goal would be able to check the request for some of the details such as GET and its return value. Appreciate the community's help.

MongChangHsi
  • 103
  • 1
  • 12

1 Answers1

0

By my opinion you not add some configuration, for resolve it automatically you can try make Integration Test for this. Like this

@WithMockUser//if you use spring secutity
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = RANDOM_PORT)
class MyTest {
    @Autowired
    private MockMvc mvc;
}

and make a test application for quickly loading environment

@SpringBootApplication
@ConfigurationPropertiesScan
@ComponentScan(lazyInit = true)//make loading is faster
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

This way can load full context configuration like prod mode, of course only for called methods if you used lazyInit = true