Spock 测试因 MissingPropertyException 而失败 [英] Spock Test Failing with MissingPropertyException

查看:37
本文介绍了Spock 测试因 MissingPropertyException 而失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a simple class that builds a RequestMessage based on a simple rule.

  • 如果在数据库中找到 MessageMetadata,则使用该元数据构建消息.
  • 否则,消息是使用提供元数据的服务构建的.
  • If MessageMetadata is found in the database, the message is built using that metadata.
  • Otherwise, the message is built using a service that provides the metadata.

这是课程和 Spock 测试.测试失败并返回 MissingPropertyException,表示无法找到使用该服务创建的 RequestMessage.

Here is the class along with a Spock test. The test fails with a MissingPropertyException, saying it cannot find the RequestMessage created using the service.

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
}

我真的很想了解为什么这不起作用.我很感激在成功测试此测试方面的任何帮助.谢谢

I would really like to understand why this doesn't work. I'm grateful for any help in testing this test successfully. Thank you

推荐答案

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

The problem is indeed the hen vs. egg problem I mentioned in my comment to jaco0646's answer. Let me recreate the core problem in an 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)

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

Just declaring requestMessage in the given: block as jaco0646 suggested and then using it as a stub result won't do it alone. You need to make sure that you first declare an object (e.g. a mock) to be returned by the builder method, but assign the result of the method call under test to another variable so you can compare the two or do whatever verification you like to perform:

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'")
  }
}

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

Now the test passes and your bootstrapping problem is solved. You cannot create an object with a method call and then specify it as an expected stub result at the same time. It makes no logical sense.

这篇关于Spock 测试因 MissingPropertyException 而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆