简体   繁体   English

Spock + Spring - 从 Stubbed @SpringBean 返回的存根始终返回 null

[英]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.

相关问题 与 Spock 的 Spring Boot 集成测试:存根方法返回 null - Spring Boot integration test with Spock: stubbed method returns null Spock 测试中未返回存根 object 方法值 - Stubbed object method value not returned in Spock test Spock:在Stubs中返回输入参数 - Spock: Return input parameter in Stubs 在Spring MVC 5中使用MultipartFile总是返回null - Working with MultipartFile in Spring MVC 5 always return null 返回的JSONObject始终为null - Returned JSONObject is always null 为什么Spring Boot MVC总是从表单中返回空值? - Why does Spring Boot MVC always return null values from my form? 将Spring从4.3.x降级到3.2.x后,Spock中的自动装配bean测试无效 - Autowired bean in spock test null after downgrading spring from 4.3.x to 3.2.x Wicket @SpringBean 和 Spring @Autowired 通过构造函数注入 - Wicket @SpringBean and Spring @Autowired with injection via constructor spring-data-neo4j findByPropertyValue方法始终返回null? - spring-data-neo4j findByPropertyValue method always return null? 为什么 Annotation @Value 在使用 Spring PropertySourcesPlaceholderConfigurer 时总是返回 null? - Why Annotation @Value return always null during using Spring PropertySourcesPlaceholderConfigurer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM