【问题标题】:Test service from with dependencies in spock使用 spock 中的依赖项测试服务
【发布时间】:2018-12-07 22:07:43
【问题描述】:

我正在使用 kotlin 和 spring 项目,现在我正在尝试测试一些服务,它有一些依赖项,我遇到了一些问题,以便获得成功的测试。也许我的设计不够好,而且我在尝试从 spy 对象调用方法时遇到问题,我遇到了问题:无法在基于接口的模拟对象上调用真正的方法“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)
        }
    }
}

【问题讨论】:

    标签: spring unit-testing kotlin spock


    【解决方案1】:

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

    Groovy Mocks 何时应该优于常规 Mocks?当规范中的代码是用 Groovy 编写的并且需要一些独特的 Groovy 模拟功能时,应该使用 Groovy 模拟。当从 Java 代码调用时,Groovy 模拟的行为类似于常规模拟。请注意,不必仅仅因为规范和/或模拟类型下的代码是用 Groovy 编写的,就必须使用 Groovy 模拟。除非您有具体的理由使用 Groovy 模拟,否则更喜欢常规模拟。

    至于您的间谍问题,您不能在接口类型上使用间谍。这是记录在here

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

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

    【讨论】:

    • 是的,你是对的,我没有阅读足够的文档,我在代码和测试中做了一些更改,现在我使用 mock 代替 Groovy 模拟。
    猜你喜欢
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    相关资源
    最近更新 更多