14

我们将 Spock 测试与 Spring 的 @ContextConfiguration 结合起来,这样我们就可以在 Spring 上下文中构建 bean,然后使用 Spock 进行实际测试。我们想将 spock 模拟注入到我们的 spring bean 中。对于 Mockito,有一个扩展程序允许您执行以下操作:

 <mockito:mock id="accountService" class="org.kubek2k.account.DefaultAccountService" />

然后将此模拟引用到其他spring bean。Spock 似乎没有这样的扩展。如果您知道如何在 Specification 类之外创建 Mocks,那么再次构建它可能不会花费太多精力。我知道创建 Spock 模拟的唯一方法是:

T Mock(Class<T> type)   

在规范中。当不在规范类中时,Spock 中是否有一些 API 可以创建 Mocks,所以我可以为 Spring 上下文创建 Spock 模拟?

4

4 回答 4

6

目前无法在规范类之外创建模拟(并在另一个规范类中使用它们)。对此有一个开放的功能请求。实现这一点应该不会太难,但它需要对 spock-core 进行一些更改。至少,需要有一种方法可以手动将模拟对象附加到另一个规范实例。MockingApi或许,将面向用户的模拟创建 API 移出基类也是有意义的。

您应该能够将 Mockito 与 Spock 一起使用,只要您将包含在 then 块中的所有验证代码包装为调用返回的辅助方法true(因为 Spock 将其视为断言)。类似的东西then: mockito { /* mockito verifications go here */ }

于 2013-05-29T10:28:09.407 回答
5

找到了一个在 Spring 应用程序中使用 Spock 模拟对象的简单解决方法。这里我的spring配置为basar bean使用了一个模拟:

@Configuration @Profile("mocking")
class MockingContext {
  @Bean Basar basar(){ new DelegatingBasar() }
}

class DelegatingBasar implements Basar {
  @Delegate Basar delegate
}

这里有一个简单的 Spock 规范,它创建和使用模拟:

@Autowired
Basar basar
Basar basarMock

def setup() {
    basarMock = Mock(Basar)
    basar.delegate = basarMock;
}

def "create a new seller"(User seller) {
    given:
        basarMock.findAllUsers() >> []
    when:
        go "/static/sellers.html"
        waitFor { $("#newUser") }
        $("#newUser").click()
        waitFor { $("#basarNumber") }
        $("#basarNumber").value(seller.basarNumber)
        $("#name").value(seller.name)
        $("#lastname").value(seller.lastname)
        $("#email").value(seller.email)
        $("#saveUser").click()
        waitFor { $("#successfullCreated") }
    then:
        1 * basarMock.saveUser({ newUser ->  
            newUser.basarNumber == seller.basarNumber
            newUser.name        == seller.name
            newUser.lastname    == seller.lastname
            newUser.email       == seller.email
        })
    where:
        seller << [ new User(basarNumber: "100", name: "Christian", lastname: "", email: ""),
                    new User(basarNumber: "ABC", name: "",          lastname: "", email: "")]
}
于 2015-03-22T10:09:17.077 回答
5

自 Spock 1.1 以来,可以在规范类之外创建模拟DetachedMockFactorySpockMockFactoryBeanspock还支持基于 XML 的配置的命名空间。您可以在文档中找到使用示例。

使用基于 Java 的配置的 Spring 测试,DetachedMockFactory如下所示:

@ContextConfiguration(classes = [TestConfig, DiceConfig])
class DiceSpec extends Specification {
    @Autowired
    private RandomNumberGenerator randomNumberGenerator

    @Subject
    @Autowired
    private Dice dice

    def "uses the random number generator to generate results"() {
        when:
            dice.roll()

        then:
            1 * randomNumberGenerator.randomInt(6)
    }

    static class TestConfig {
        private final mockFactory = new DetachedMockFactory()

        @Bean
        RandomNumberGenerator randomNumberGenerator() {
            mockFactory.Mock(RandomNumberGenerator)
        }
    }
}

@Configuration
class DiceConfig {
    @Bean
    Dice dice(RandomNumberGenerator randomNumberGenerator) {
        new Dice(randomNumberGenerator)
    }
}

基于 XML 的配置看起来像这样:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:spock="http://www.spockframework.org/spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.spockframework.org/spring http://www.spockframework.org/spring/spock.xsd">
    <spock:mock id="randomNumberGenerator" class="RandomNumberGenerator"/>
</beans>

确保包含spock-spring依赖项:

testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.1-groovy-2.4-rc-3'
于 2017-03-25T17:06:55.780 回答
0

这对于“纯春天”来说非常简单:

def parentAppCtx = new StaticApplicationContext()
parentAppCtx.beanFactory.registerSingleton("myBean", Mock(MyClass))
parentAppCtx.refresh()
def appCtx = new ClassPathXmlApplicationContext("spring-config.xml", parentAppCtx)

当然,这假设您正在正确分解您的 Spring 配置。(例如,如果您重新定义"myBean"in ,则将使用in 中spring-config.xml的定义,因为它本质上是一个 Map,并且最近放入其中的定义将获胜。)spring-config.xmlApplicationContext

于 2015-09-15T22:22:44.783 回答