Как издеваться над статическим методом стороннего вызова API с помощью spock?

Я использую фреймворк micronaut и spock для написания тестового примера API. Я пытаюсь создать тестовый пример своего API, который внутренне вызывает PaymentIntent.retrieve() статический метод стороннего API. Я хочу издеваться над этим вызовом стороннего URL и вместо этого вернуть fakeObject PaymentIntent.

Вот созданный мной образец тестового примера, который выполняет фактический сторонний статический метод api:

@Inject Service myService;

@Unroll
void "method returns nothing"() {
  given:
  PaymentIntent paymentIntent = new PaymentIntent()
  Mock(PaymentIntent)
  PaymentIntent.retrieve("pi_123", requestOptions) >> paymentIntent
  
  when:
  def result = myService.getPayment("", "pi_123", obj)

  then:
  result.amount == paymentIntent.amount
}

Может ли кто-нибудь подсказать мне, как можно ограничить выполнение фактического API?

Я сослался на эти уже заданные вопросы, но в моем случае это не сработало. Макет статического метода с GroovyMock или аналогичным в Spock


person Mehul Trivedi    schedule 05.01.2021    source источник
comment
Добро пожаловать в SO. Предлагаем вам узнать, что такое MCVE и как он помогает получить нужные ответы. Тестовый фрагмент, даже не являющийся полным классом, в сочетании с тем фактом, что вы не предоставили тестируемый класс, затрудняет ответ на ваш вопрос, поэтому Джеффу в своем ответе пришлось строить предположения. Предположение о том, что ваш тестируемый класс написан на Groovy, может быть истинным или ложным, в зависимости от того, подойдет ли его ответ для вас или нет.   -  person kriegaex    schedule 06.01.2021


Ответы (2)


Решение будет зависеть от того, на каком языке написан класс, вызывающий PaymentIntent.retrieve. Ниже предполагается, что Groovy, потому что вопрос помечен тегом groovy.

import com.stripe.exception.StripeException
import com.stripe.model.PaymentIntent
import com.stripe.net.RequestOptions

import javax.inject.Singleton

@Singleton
class MyService {
    PaymentIntent getPayment(String s1, String s2, RequestOptions options) throws StripeException {
        PaymentIntent.retrieve s1, options
    }
}
import com.stripe.model.PaymentIntent
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import spock.lang.Specification

import javax.inject.Inject

@MicronautTest
class MyServiceSpec extends Specification {
    @Inject
    MyService myService;

    void "method returns nothing"() {
        when:
        PaymentIntent paymentIntent = new PaymentIntent()
        paymentIntent.amount = 42
        GroovySpy(PaymentIntent, global: true)
        1 * PaymentIntent.retrieve("pi_123", _) >> paymentIntent

        def result = myService.getPayment("pi_123", null, null)

        then:
        result.amount == 42
    }
}
person Jeff Scott Brown    schedule 05.01.2021

Издеваться над статикой - нетривиальная задача. Я бы рекомендовал выделить сторонний вызов в отдельный метод, который можно переопределить в модульном тесте.

Предположим, ваш Service.getPayment() выглядит как

  class MyService {
    PaymentIntent getPayment(String s1, String s2, RequestOptions options) throws StripeException {
        // some logic here
        // ...

        PaymentIntent.retrieve s1, options
    }
  }

Позвольте рефакторингу

  class MyService {
    PaymentIntent getPayment(String s1, String s2, RequestOptions options) throws StripeException {
        // some logic here
        // ...

        doRetrieveCall s1, options
    }

    PaymentIntent doRetrieveCall(String s1, RequestOptions options) throws StripeException {
        PaymentIntent.retrieve s1, options
    }
  }

Ваш модульный тест

  given:
    def myService = new Service() {
      // overriden
      PaymentIntent doRetrieveCall(String s1, RequestOptions options) throws StripeException {
        // todo validate of the s1 for "pi_123"
        // todo validate of the options

        // return a fake instance
        new PaymentIntent()
      }
    }
  
  when:
    def result = myService.getPayment("", "pi_123", obj)

  then:
    result.amount == paymentIntent.amount
person Dmytro Maslenko    schedule 17.01.2021