[英]Spock + Spring - Stubs returned from Stubbed @SpringBean always return null
I am attempting to use Spock to create an integration test around a Spring application.我正在尝试使用 Spock 围绕 Spring 应用程序创建集成测试。 As it is not a Spring Boot application and the
@SpringBootTest
annotation interfered significantly with the app's initialization, I am using a minimal configuration.由于它不是 Spring Boot 应用程序,并且
@SpringBootTest
注释严重干扰了应用程序的初始化,因此我使用的是最小配置。
I specifically need to stub a service in my app that returns objects of type Message
;我特别需要在我的应用程序中存根一个返回
Message
类型对象的服务; in the actual app these objects would come from a third-party vendor's library and they cannot be instantiated or subclassed, nor do their members have setters, so my only option is to create Stub
s for them.在实际应用程序中,这些对象将来自第三方供应商的库,它们不能被实例化或子类化,它们的成员也没有设置器,所以我唯一的选择是为它们创建
Stub
。 However, with this current configuration (I've simplified the test significantly just to get the gist across):但是,使用这种当前配置(我已经大大简化了测试,只是为了了解要点):
@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 }
}
}
}
Internally, the ServiceUnderTest.businessMethod()
is using the Message
object like this:在内部,
ServiceUnderTest.businessMethod()
使用Message
对象,如下所示:
restService.getMessage(sid).getStatus() // should be "stubbed status"; always evaluates to null
however, every method of the Message
stub always returns null regardless of whether I have defined a behavior for it.但是,无论我是否为它定义了一个行为,
Message
stub的每个方法总是返回 null。 The Message
objects must return specific values from its getters for the test to work. Message
对象必须从其 getter 中返回特定值才能使测试正常工作。 I would prefer to not have to declare every Message
stub as its own @SpringBean
;我宁愿不必将每个
Message
存根声明为自己的@SpringBean
; I need to eventually expand the test to use several different Message
stub objects.我最终需要扩展测试以使用几个不同的
Message
存根对象。 I don't need mocks or spies because the number of invocations of RestService
's methods doesn't matter, I just need it to emit proper stubs for ServiceUnderTest
to chew on.我不需要模拟或间谍,因为调用
RestService
的方法的次数并不重要,我只需要它发出适当的存根供ServiceUnderTest
咀嚼。 Apologies if this question is unusual or I've missed something obvious;如果这个问题不寻常或者我错过了一些明显的东西,我们深表歉意; I'm slightly oblivious to Spock's notion of lifecycle, and the waters have been especially muddied with the addition of the Spring extension.
我对 Spock 的生命周期概念有点忘记,而且随着 Spring 扩展的添加,水变得特别混乱。
I discovered the answer soon after writing this, but just for posterity;写完这篇文章后我很快就找到了答案,但只是为了后代; the third-party
Message
class is declared as final
and thus can't be subclassed;第三方
Message
类被声明为final
,因此不能被子类化; Spock was creating stubs for them but silently failing to add the overridden mock methods. Spock 正在为它们创建存根,但默默地没有添加被覆盖的模拟方法。 I ended up using PowerMockito to remove this limitation;
我最终使用PowerMockito来消除这个限制; however this interfered with collecting test coverage metrics, so I instead used a wrapper class that can be mocked and used it everywhere in my code the original Message class was:
然而,这干扰了收集测试覆盖率指标,所以我改用了一个可以模拟的包装类,并在我的代码中到处使用它,原来的 Message 类是:
public class MessageWrapper {
public MessageWrapper(Message from) {...}
}
it's an extra bit of headache, but it was necessary because test coverage was required in this case.这有点让人头疼,但这是必要的,因为在这种情况下需要测试覆盖率。 There also seems to be a promising Spock-specific mocking utility that will mock final classes, but I haven't tested it nor do I know if it will interfere with collecting coverage metrics like PowerMockito does.
似乎还有一个很有前途的特定于 Spock 的模拟实用程序可以模拟最终类,但我没有测试过它,也不知道它是否会像 PowerMockito 那样干扰收集覆盖率指标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.