简体   繁体   中英

Mock trying to initialize fields

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)
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM