简体   繁体   English

Spock模拟-我的方法调用值没有被模拟

[英]Spock Mocking - my method call values aren't mocked

When calling getMarkup() in my static method of my helper class it throws a NPE. 在助手类的静态方法中调用getMarkup() ,它将引发NPE。 What I did was mocking both the MarkupMaker and it's return value, a instance of Markup. 我所做的是模拟MarkupMaker及其返回值,即Markup的实例。 Ultimately I want to call toString() of the Markup instance. 最终,我想调用Markup实例的toString() Whatever I do - the call of getMarkup() is throwing a NPE. 无论我做什么getMarkup()的调用都会getMarkup() NPE。 I cannot find any documentation telling me how to mock method calls value in spock in detail. 我找不到任何文档可以告诉我如何在spock中详细模拟方法调用值。

EDIT: I added the example. 编辑:我添加了示例。 The call of maker.getMarkup() return null even tho I mocked it in the spock test. 甚至我在spock测试中嘲笑maker.getMarkup()的调用都返回null。

Test.groovy 测试规则

class TestExample extends Specification {

    @Shared
    MarkupMaker makerMock = Mock()
    @Shared
    MarkupObject markupMock = Mock()

    def setup() {
        markupMock.toString() >> "headline1"
        makerMock.getMarkup() >> markupMock
    }

    @Unroll
    def "Should return a Markupvalue #expectedvalue"(MarkupMaker helper, int tabElementIndex, String expectedValue) {
        expect:
        MarkupHelper.getMarkupForIndex(helper, tabElementIndex) == expectedValue
        where:
        helper    | tabElementIndex | expectedValue
        makerMock | 1               | "headline1"

    }

}

Helper.java (executed the method of the mocked object) Helper.java (执行了模拟对象的方法)

public class MarkupHelper {

  public static MarkupObject getMarkupForIndex(MarkupMaker maker, int index){
    if(index == 1){
      maker.getMarkup();
    }
    return null;
  }
}

MarkupMaker.java (one of the mocked objects) MarkupMaker.java模拟对象之一)

public class MarkupMaker {

  public MarkupObject getMarkup() {
    return new MarkupObject();
  }
}

MarkupObject.java (the last mocked object which holds the value tested for) MarkupObject.java (保存测试值的最后一个模拟对象)

public class MarkupObject {
  @Override
  public String toString() {
    return "headline1";
  }
}

删除@Shared上的@Shared ,因为@Shared不支持它。

In your example you have provided, MarkupHelper will always return null. 在您提供的示例中,MarkupHelper将始终返回null。 You are simply calling the maker.getMarkup() and not doing anything with it. 您只是在调用maker.getMarkup()而不对其进行任何操作。 So the execution will continue and return null . 因此执行将继续并return null

Leonard's answer is the correct one, since your use of @Shared why you are getting the NPE on the mocked object, but your test will still not be satisfied due to your MarkupHelper not actually doing what you'd expect. 伦纳德的答案是正确的,因为您使用@Shared为何要在@Shared对象上获得NPE,但由于您的MarkupHelper并未实际执行预期的工作,因此您的测试仍然无法令人满意。

Similarly, your MarkupObject mock that is stubbing the toString isn't going to work since by the time you want to use it, it'll be outside of the simulation and therefore won't be used. 同样,对toString进行存根处理的MarkupObject模拟将无法工作,因为到您要使用它时,它将不在模拟范围内,因此将不被使用。 In order to handle that, you should have your MarkupHelper return a String like: 为了解决这个问题,您应该让您的MarkupHelper返回类似以下的字符串:

public static String getMarkupForIndex(MarkupMaker maker, int index){
    if(index == 1){
        return maker.getMarkup().toString();
    }
    return null;
}

If you still want your MarkupHelper to return a MarkupObject, in your test you'll instead need to create an expected MarkupObject that has the same properties as your actual one. 如果仍然希望MarkupHelper返回一个MarkupObject,则在测试中,您需要创建一个预期的MarkupObject,该属性具有与实际属性相同的属性。

I would recommend to create and mock all objects inside every test method. 我建议在每个测试方法中创建和模拟所有对象。 In this case you will be sure every test is isolated and shared data will not affect on your result. 在这种情况下,您将确保隔离每个测试,并且共享数据不会影响您的结果。

Concerned to your example I would cover the getMarkupForIndex method by these 2 tests: 关于您的示例,我将通过以下两个测试来介绍getMarkupForIndex方法:

@Unroll
def "getMarkupForIndex(..) returns null when the given index is #givenIndex"(){
    given:
    def mockedMaker = Mock(MarkupObject)

    when:
    def actualResult = MarkupHelper.getMarkupForIndex(mockedMaker, givenIndex)

    then:
    actualResult == null
    0 * _._ // no mock interaction at all

    where:
    givenIndex << [0, 2, 3]
}

def "getMarkupForIndex(..) returns a markup object when the given index is 1"(){
    given:
    def expectedMarkupObject = new MarkupObject()
    def mockedMaker = Mock(MarkupMaker) {
        getMarkup() >> expectedMarkupObject
    }

    when:
    def actualResult = MarkupHelper.getMarkupForIndex(mockedMaker, 1)

    then:
    actualResult.is(expectedMarkupObject)
    1 * mockedMaker.getMarkup()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM