【发布时间】:2019-12-18 00:19:11
【问题描述】:
我正在尝试使用 Spock 围绕 Spring 应用程序创建集成测试。由于它不是 Spring Boot 应用程序,并且 @SpringBootTest 注释严重干扰了应用程序的初始化,因此我使用的是最小配置。
我特别需要在我的应用程序中存根一个返回 Message 类型对象的服务;在实际应用程序中,这些对象将来自第三方供应商的库,它们不能被实例化或子类化,它们的成员也没有设置器,所以我唯一的选择是为它们创建 Stubs。但是,使用当前的配置(我已经大大简化了测试,只是为了了解要点):
@ContextConfiguration([TestSetup]) // supplies actual Spring beans including some JPA repos
class LogicSpec extends Specification {
@SpringBean
RestService restService = Stub()
@Autowired
ServiceUnderTest sut
@Autowired
SomeJPARepo repository;
def 'should do some business logic'() {
given:
Message m = new Stub() {
getStatus() >> "stubbed status"
}
restService.getMessage(_ as String) >> {
m
}
when:
sut.businessMethod()
then:
// just checking for side effects that `businessMethod` causes, no mocks being matched against
assert repository.findAll().every { it.processed == true }
}
}
}
在内部,ServiceUnderTest.businessMethod() 使用 Message 对象,如下所示:
restService.getMessage(sid).getStatus() // should be "stubbed status"; always evaluates to null
然而,每个方法Message存根总是返回null,不管我是否为它定义了一个行为。 Message 对象必须从它的 getter 中返回特定值才能使测试工作。我宁愿不必将每个Message 存根声明为自己的@SpringBean;我最终需要扩展测试以使用几个不同的Message 存根对象。我不需要模拟或间谍,因为RestService 的方法的调用次数无关紧要,我只需要它为ServiceUnderTest 发出适当的存根来咀嚼。如果这个问题不寻常或者我错过了一些明显的东西,我们深表歉意;我有点忘记 Spock 的生命周期概念,而且随着 Spring 扩展的添加,水变得特别混乱。
【问题讨论】:
-
Message具体是什么? (还要注意assert在then块中是不必要的,并且您通常不应该比较 Java 或 Groovy 中的布尔常量,所以只需then: repository.findAll().every { it.processed } -
(另外,这看起来真的是一个unit测试,那你为什么不直接使用
new ServiceUnderTest(mockRepo, rest)呢?) -
我也有同样的问题。你有没有找到解决办法。所以请回答你自己的问题。