有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spock测试失败,缺少PropertyException

我有一个简单的类,它基于一个简单的规则构建一个RequestMessage

  • 如果在数据库中找到MessageMetadata,则使用该元数据生成消息
  • 否则,将使用提供元数据的服务构建消息

这是课程和斯波克测试。测试失败,出现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
}

我真的很想理解为什么这不起作用。我非常感谢在成功测试这项测试中得到的任何帮助。多谢各位


共 (2) 个答案

  1. # 1 楼答案

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

    package de.scrum_master.stackoverflow.q60143388;
    
    public class RequestMessage {}
    
    package de.scrum_master.stackoverflow.q60143388;
    
    public class MessageService {
      MessageBuilder messageBuilder;
    
      public RequestMessage getMessage(String id) {
        return messageBuilder.buildNew(id);
      }
    }
    
    package de.scrum_master.stackoverflow.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.stackoverflow.q60143388.MessageServiceTest
    
        at de.scrum_master.stackoverflow.q60143388.MessageServiceTest.build request message(MessageServiceTest.groovy:17)
    

    仅仅将given:块中的requestMessage声明为建议的jaco0646,然后将其用作存根结果,并不能单独完成这项工作。您需要确保首先声明一个对象(例如,一个mock)将由builder方法返回,但要将测试中的方法调用的结果分配给另一个变量,以便您可以比较这两个变量,或者执行任何您想执行的验证:

    package de.scrum_master.stackoverflow.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'")
      }
    }
    

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

  2. # 2 楼答案

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

    Spock lifecycle有一些令人惊讶的行为,其中之一是interactionswhen块之前被处理