【问题标题】:How can I mock part of a Spring Boot service for ALL of my Spock Integration tests?如何为我的所有 Spock 集成测试模拟部分 Spring Boot 服务?
【发布时间】:2019-05-31 17:58:05
【问题描述】:

我正在使用 Spock 为我的 Spring Boot 应用程序创建集成测试,但我无法弄清楚如何为我的 所有 测试用例模拟服务的一部分。

我的应用写入在 Gremlin Graph 模式下运行的 Azure Cosmos 数据库,由于我不知道任何内存数据库可以充分模拟它,我想确保任何服务只写入我的开发数据库与标有当前测试的随机 UUID 的实体交互。因此,任何读取/写入数据库的服务都需要确保在任何查询中包含当前的测试 ID。

通过 Spock 在抽象基类中模拟几个重用方法的最佳方法是什么?

GraphService.groovy

abstract class GraphService {
    @Autowired 
    protected GraphTraversalSource g

    protected GraphTraversal buildBaseQuery() {
        return g.V()
    } 

    protected GraphTraversal buildBaseCreationQuery(String label) {
        return g.addV(label)
    }
}

几个数据库搜索/修改服务继承了上述类。对于我所有的测试,我想要 g.V().has("testID", testId) 而不是 g.V() 而不是 g.addV(label) 我想要 g.addV(label).property("testID", testId)。如何在我的所有集成测试中实现这一点?我尝试创建一个指定此行为的基本规范类,但它不起作用。

TestConfig.groovy

@Configuration
class TestConfig {
    @Bean
    @Primary
    GraphPersistenceService persistenceService(
            GraphTraversalSource g) {
        DetachedMockFactory mockFactory = new DetachedMockFactory()
        GraphPersistenceService persistenceService = mockFactory.Stub( //Mock doesn't work either
            [constructorArgs: [g]], GraphPersistenceService)
        return graphPersistenceService
    }
}

BaseIntegrationTest.groovy

class BaseIntegrationTest extends Specification {
    @Autowired
    TestUtil testUtil

    @Autowired
    GraphTraversalSource g

    @Autowired
    GraphPersistenceService persistenceService

    def setup() {
        persistenceService.buildBaseQuery >> g.V().has("testID", testUtil.id)
        persistenceService.buildBaseCreationQuery(_ as String) >> { label ->
            g.addV(label).property("testID", testUtil.id)
        }
    }

    def cleanup() {
        testUtil.removeAllEntitiesWithCurrentTestId()
    }
}

然后在实际测试中:

@SpringBootTest(classes = MyGraphApplication.class)
@ContextConfiguration(classes = [GraphDbConfig.class, TestConfig.class])
@ActiveProfiles("test")
@TestPropertySource(locations = 'classpath:application-local.properties')
class UserOfPersistenceServiceSpec extends BaseIntegrationTest {
    @Autowired
    UserOfGraphPersistenceService userOfPersistenceService

    def "Can create a bunch of vertices"() {
        expect:
        userOfPersistenceService.createABunchOfVertices() == 5
    }
}

附言。我正在使用 Spring 1.5.10.RELEASE 和 groovy 2.4.15 ...

【问题讨论】:

    标签: spring-boot groovy mocking spock


    【解决方案1】:

    如果您可以选择升级到 Spock 1.2,我建议放弃 TestConfig 类并使用 @SpringBean 注释。

    这是我在测试中如何设置它的示例:

    @ActiveProfiles(["integrationtest"])
    @DirtiesContext
    abstract class IntegrationTest extends Specification {
    
        @SpringBean
        EurekaClient eurekaClient = Mock() {
            getNextServerFromEureka(*_) >> Mock(InstanceInfo) {
                getHomePageUrl() >> "test.test"
            }
        }
    
    //    ... other stuff
    }
    

    【讨论】:

    • 谢谢!这看起来很有希望,但是如果我正确阅读了其中一些文章,我认为我需要以某种方式使用 Spy。我希望我的服务的其余部分正常运行,我只想覆盖几个特定的​​方法。 Mock 会要求我重新定义我想要响应的每个方法,对吧?
    • @SnoopDougg 是的,在这种情况下你想要一个间谍。其余的应该是一样的
    猜你喜欢
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2020-01-15
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    相关资源
    最近更新 更多