通过spock中的依赖项测试服务

时间:2018-12-07 22:07:44

标签: spring unit-testing kotlin spock

我正在与kotlin和spring项目合作,现在我正在尝试对某些服务进行测试,该服务具有某些依赖性,为了获得成功测试,我遇到了一些问题。也许我的设计不够好,而且我尝试从间谍对象调用该方法时遇到问题,但我遇到了问题:无法在基于接口的模拟对象上调用真实方法“ getClubhouseFor”。这是我的代码,请问您对我做的不好有什么了解。

提前谢谢!!! 这是我的代码:

import com.espn.csemobile.espnapp.models.UID
import com.espn.csemobile.espnapp.models.clubhouse.*
import com.espn.csemobile.espnapp.services.clubhouse.AutomatedClubhouseService
import com.espn.csemobile.espnapp.services.clubhouse.ClubhouseService
import com.espn.csemobile.espnapp.services.clubhouse.StaticClubhouseService
import com.espn.csemobile.espnapp.services.clubhouse.contexts.ClubhouseContext
import com.espn.csemobile.espnapp.services.core.CoreService
import rx.Single
import spock.lang.Specification

class ClubhouseServiceImplTest extends Specification {


    StaticClubhouseService staticClubhouseService = GroovyStub()
    AutomatedClubhouseService automatedClubhouseService = GroovyStub()
    CoreService coreService =  GroovyStub()
    ClubhouseContext clubhouseContext = GroovyMock()
    Clubhouse clubHouse
    ClubhouseLogo clubhouseLogo
    ClubhouseService spy = GroovySpy(ClubhouseService)

    void setup() {
        clubhouseLogo = new ClubhouseLogo("http://www.google.com", true)
        clubHouse = new Clubhouse(new UID(), "summaryType", ClubhouseType.League, new ClubhouseLayout(), "summaryName", "MLB", clubhouseLogo, "http://www.google.com", "liveSportProp",new ArrayList<Integer>(), new ArrayList<ClubhouseSection>(),new ArrayList<ClubhouseAction>(), new HashMap<String, String>())
    }



    def "GetClubhouseFor"() {
        given:
        staticClubhouseService.getClubhouseFor(clubhouseContext) >> buildClubHouseMockService()
        // The idea here is to get different responses it depends on the class of call.
        automatedClubhouseService.getClubhouseFor(clubhouseContext ) >> buildClubHouseMockService()
        spy.getClubhouseFor(clubhouseContext) >> spy.getClubhouseFor(clubhouseContext)
        when:
        def actual = spy.getClubhouseFor(clubhouseContext)
        then:
        actual != null
    }

    def buildClubHouseMockService(){
        return Single.just(clubHouse)
    }
}

接下来是测试中涉及的类:

import com.espn.csemobile.espnapp.models.clubhouse.*
import com.espn.csemobile.espnapp.services.clubhouse.contexts.ClubhouseContext
import com.espn.csemobile.espnapp.services.core.CoreService
import org.springframework.context.annotation.Primary
import org.springframework.context.annotation.ScopedProxyMode
import org.springframework.stereotype.Service
import org.springframework.web.context.annotation.RequestScope
import rx.Single

interface ClubhouseService {
    fun getClubhouseFor(context: ClubhouseContext): Single<Clubhouse?>
}

@Service
@RequestScope(proxyMode = ScopedProxyMode.NO)
@Primary
class ClubhouseServiceImpl(private val clubhouseContext: ClubhouseContext,
                        private var staticClubhouseService: StaticClubhouseService,
                       private var automatedClubhouseService: AutomatedClubhouseService,
                       private val coreService: CoreService?): ClubhouseService {

    override fun getClubhouseFor(context: ClubhouseContext): Single<Clubhouse?> {
        return staticClubhouseService.getClubhouseFor(clubhouseContext).flatMap { clubhouse ->
            if (clubhouse != null) return@flatMap Single.just(clubhouse)

            return@flatMap automatedClubhouseService.getClubhouseFor(clubhouseContext)
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好吧,首先GroovySpyGroovyStub对于Java或Kotlin类没有意义,因为Groovy模拟的特殊功能仅适用于Groovy类。因此,如果这是使用的原因,请不要期望能够以这种方式模拟构造函数或静态方法。 here中也有记录:

  

什么时候应该比常规的模仿更喜欢Groovy的模仿?当使用Groovy 编写规范下的代码时,应使用Groovy模仿,并且需要某些独特的Groovy模仿功能。当从Java代码调用时,Groovy模拟将表现得像常规模拟一样。请注意,仅因为规范和/或模拟类型下的代码是用Groovy编写的,所以不必使用Groovy模拟。除非您有具体的理由使用Groovy模拟,否则请选择常规模拟。

关于间谍的问题,您不能在接口类型上使用间谍。记录在here中:

  

间谍总是基于真实对象。因此,您必须提供一个类类型而不是接口类型,以及该类型的任何构造函数参数。

因此,要么只是切换到Mock或Stub,它们都适用于接口类型,要么监视实现类。无论如何,我的主要建议是先阅读文档,然后尝试使用Spock这样的新工具。我的印象是您以前没有使用过Spock,但我当然会错了。