-1

Src Code

class ReportingUtil {
    companion object {
        private val gson = Gson()
        private val amazonSNS = AmazonSNSClientBuilder.standard().build()
        private val topicArn = AppConfig.findString(TOPIC_ARN)
    }

    /**
     * This function will convert object to json format and will publish to SNS topic.
     * [invoiceData] -
     */
    fun publishFailureInvoiceToSNS(invoiceData: InvoiceData) {
        val jsonInvoiceMap = gson.toJson(invoiceData)
        log.info("The Invoice : $invoiceData is converted to json format : $jsonInvoiceMap")
        amazonSNS.publish(topicArn, jsonInvoiceMap)
        log.info("Json invoice: $jsonInvoiceMap is published to the sns topic")
    }
}

Unit Test

@Test
fun `test to publish invoice data to SNS topic`(){
    initConfig()
    val amazonSNS = mockk<AmazonSNS>()
    val invoiceData = InvoiceData("a", "a", "a", BigDecimal(6), "a", "a", mutableMapOf("a" to "a"))
    val reportingUtil = ReportingUtil()
    every { 
            amazonSNS.publish("topicArn", "jsonInvoiceMap") 
   } returns PublishResult().withMessageId("MESSAGE_ID")
    reportingUtil.publishFailureInvoiceToSNS(invoiceData)
}

This is giving me following error on src publish line,

com.amazonaws.services.sns.model.InvalidParameterException: Invalid parameter: TopicArn or TargetArn Reason: no value for required parameter (Service: AmazonSNS; Status Code: 400; Error Code: InvalidParameter; Request ID: 5f1732ac-d63e-5e13-964c-65c312e218d7; Proxy: null)

My use-case does not allow me to use dependency injection, therefore I made client static here.

I also want to add my custom optimization plans in catalyst which will also be triggered at build time. Is there any way to do all this before execution?

user4157124
  • 2,809
  • 13
  • 27
  • 42
Akash Patel
  • 189
  • 1
  • 5
  • 13

1 Answers1

1

The amazonSNS you have mocked is not the one used to publish data in publishFailureInvoiceToSNS is not the one. So, when you call publishFailureInvoiceToSNS you are actually calling the real SNS API.

You have to refactor your code to use some kind of dependency injection. At least you should make it configurable. There are no use-cases that "does not allow to use DI".

If you're using JUnit 5, you could use these helpers for AWS clients injections in test. I would also recommend using localstack for unit tests.

madhead
  • 31,729
  • 16
  • 153
  • 201
  • Okay but due to some reason...I am not allowed to use DI here. how can I mock it in that case? – Akash Patel Jun 27 '20 at 15:18
  • Name the reason? – madhead Jun 27 '20 at 15:52
  • this is basically a utility pakcage...this package will be integrated by many of my clients. these clients uses spring, guice, dagger frameworks etc so there will be problem if i use any one of these frameworks – Akash Patel Jun 27 '20 at 17:01
  • So it's just their responsibility to provide a client. Look, you're using `AmazonSNSClientBuilder.standard().build()`. But what if your clients need to change the region? They should be able to configure the client. – madhead Jun 27 '20 at 20:34