I have a class that I am trying to mock and call a method on it -
@Component open class CloudStorageService {
@Autowired lateinit var s3Client: AmazonS3
fun getSizeOfFirstMatchedObject(bucketName: String, directory: String, prefix: String): Long {
val request = ListObjectsRequest().withBucketName(bucketName).withPrefix("$directory/$prefix")
val listObjects = s3Client.listObjects(request)
val objectSummary = listObjects.objectSummaries.first()
val size = objectSummary.size
return size / (1024 * 1024)
}
}
I am using this method in another class as -
@Service
open class SizingService(private val cloudStorageService: CloudStorageService) {
fun methodName() {
...
val fileSize = cloudStorageService.getSizeOfFirstMatchedObject("bucketName", "filename", "prefix") // trying to mock this call
...
}
}
My Test File:
@ActiveProfiles("test")
@RunWith(SpringRunner::class)
@SpringBootTest(classes = [TestAppConfig::class])
class SizingServiceTest {
@Mock private lateinit var cloudStorageService: CloudStorageService
@Before
fun setUp() {
MockitoAnnotations.openMocks(this)
sizingService = SizingService(cloudStorageService)
}
@Test
fun shouldReturnDropletSizeForChainBusinessesCorrectly() {
`when`(cloudStorageService.getSizeOfFirstMatchedObject(eq("b1")!!, eq("filename"), eq(prefix))).thenReturn(200)
}
}
The s3Client is initialized as a bean in my AppConfig -
@Configuration
@EnableTransactionManagement
@EnableScheduling
open class AppConfig {
@Value("\${S3_REGION}") lateinit var awsRegion: String
@Value("\${S3_ACCESS_KEY}") lateinit var accessKey: String
@Value("\${S3_SECRET_KEY}") lateinit var secretKey: String
@Bean(name = ["s3Client"])
open fun s3Client(): AmazonS3 {
return AmazonS3ClientBuilder.standard().withRegion(awsRegion).withCredentials(AWSStaticCredentialsProvider(BasicAWSCredentials(accessKey, secretKey))).build()
}
}
But when I run the test, I get a failure saying s3Client is uninitialized. Why is it even trying to initialize the s3Client in CloudStorageService
when it is a mock ?
lateinit property s3Client has not been initialized
kotlin.UninitializedPropertyAccessException: lateinit property s3Client has not been initialized
at com.service.CloudStorageService.getS3Client(CloudStorageService.kt:33)
at com.service.CloudStorageService.getSizeOfFirstMatchedObject(CloudStorageService.kt:113)
at com.service.SizingServiceTest.shouldReturnDropletSizeForChainBusinessesCorrectly(SizingServiceTest.kt:219)
How do I properly mock this method ?
I made the method that I am mocking open
and the mocking worked. But I have no idea why mockito was trying to initialize if the method is not open. The error message also did not help.
Can someone explain what mockito is actually doing and how open
on a method allows the mock to happen ?
// Only Change I did was adding `open`.
open fun getSizeOfFirstMatchedObject(bucketName: String, directory: String, prefix: String): Long {
val request = ListObjectsRequest().withBucketName(bucketName).withPrefix("$directory/$prefix")
val listObjects = s3Client.listObjects(request)
val objectSummary = listObjects.objectSummaries.first()
val size = objectSummary.size
return size / (1024 * 1024)
}