Spock 测试因 MissingPropertyException 而失败

Spock Test Failing with MissingPropertyException

我有一个简单的 class,可以根据简单的规则构建 RequestMessage

这是 class 以及 Spock 测试。测试失败并显示 MissingPropertyException,表示无法找到使用该服务创建的 RequestMessage

class MessageService{
    MessageBuilder messageBuilder;
    MessageRepository messageRepository;
    MessageMetadaProvider messageMetaDataProvider;

    public RequestMessage getMessage(String id ) {
        try {
            MessageMetadata metadata = repository.findDefaulMessage(id);
            RequestMessage requestMessage = builder.createMessage(metadata);
            return requestMessage;
        } catch (DataNotFoundException e) {
            e.printStackTrace();
        }
        MessageMetadata metadata = messageMetaDataProvider.createNewMessageMetadata(id);
        RequestMessage message = messageBuilder.buildNew(id , metadata);
        return message;
    }
}

def "Build Request Message  "() {
    given:
    String id = '12345'
    MessageBuilder messageBuilder = Mock()
    MessageRepository messageRepository = Mock()
    MessageMetadaProvider messageMetaDataProvider = Mock()
    MessageService service = createMessageService(messageRepository,messageBuilder,messageMetaDataProvider)
    MessageMetadata metadata = new MessageMedata(id, MessageType.DEFAULT)
    when:
    RequestMessage requestMessage = messageService .getMessage(id )
    then:
    1 * messageRepository.repository.findDefaulMessage(id) >> {throw new DataNotFoundException("Not Found")}
    1 * messageMetaDataProvider.createNewMessageMetadata(id) >> metadata
    1  *  messageBuilder.buildNew(id , metadata) >> requestMessage
}

我真的很想知道为什么这行不通。对于成功测试此测试的任何帮助,我深表感谢。谢谢

尝试在 given 块而不是 when 块中声明 requestMessage

Spock lifecycle has some surprising behaviors, one of which is that interactionswhen之前 被处理。

问题确实是我在对 jaco0646 的回答的评论中提到的母鸡与鸡蛋的问题。让我在 MCVE:

中重现核心问题
package de.scrum_master.Whosebug.q60143388;

public class RequestMessage {}
package de.scrum_master.Whosebug.q60143388;

public class MessageService {
  MessageBuilder messageBuilder;

  public RequestMessage getMessage(String id) {
    return messageBuilder.buildNew(id);
  }
}
package de.scrum_master.Whosebug.q60143388

import spock.lang.Specification

class MessageServiceTest extends Specification {
  def "build request message"() {
    given:
    def id = "12345"
    MessageBuilder messageBuilder = Mock()
    MessageService messageService = new MessageService()
    messageService.messageBuilder = messageBuilder

    when:
    RequestMessage requestMessage = messageService.getMessage(id)

    then:
    1 * messageBuilder.buildNew(id) >> requestMessage
  }
}

这将产生:

groovy.lang.MissingPropertyException: No such property: requestMessage for class: de.scrum_master.Whosebug.q60143388.MessageServiceTest

    at de.scrum_master.Whosebug.q60143388.MessageServiceTest.build request message(MessageServiceTest.groovy:17)

只是按照 jaco0646 的建议在 given: 块中声明 requestMessage 然后将其用作存根结果不会单独完成。您需要确保首先声明一个对象(例如模拟)由构建器方法返回,但是将被测方法调用的结果分配给另一个变量,以便您可以比较两者或进行任何您喜欢的验证执行:

package de.scrum_master.Whosebug.q60143388

import spock.lang.Specification

class MessageServiceTest extends Specification {
  def "build request message"() {
    given:
    def id = "12345"
    RequestMessage requestMessage = Mock()
    MessageBuilder messageBuilder = Mock()
    MessageService messageService = new MessageService()
    messageService.messageBuilder = messageBuilder

    when:
    RequestMessage result = messageService.getMessage(id)

    then:
    1 * messageBuilder.buildNew(id) >> requestMessage
    result.toString().startsWith("Mock for type 'RequestMessage'")
  }
}

现在测试通过了,你的引导问题也解决了。您不能使用方法调用创建对象,然后同时将其指定为预期的存根结果。这没有逻辑意义。