【问题标题】:Using Spock/Groovy to test a Java method that extends HashMap - how to mock HashMap get method?使用 Spock/Groovy 测试扩展 HashMap 的 Java 方法 - 如何模拟 HashMap 获取方法?
【发布时间】:2022-01-06 00:06:32
【问题描述】:

在我们的代码库中,我们使用一个特定的类映射来存储授权请求的结果,包括某人是否有授权进入。

目前正在编写一些包含此内容的单元测试(我很少练习),我们的代码的修改版本供您查看:

public class TestResultMap extends HashMap<String, TestResult> {

    private static final long serial = -1234567890L;

    public boolean isAuthorized(String resource) {
        TestResult result = get(resource);
        if (result == null) {
            throw new RunExcept("Authorization not calculated");
        }
        return result.isAuthorized();
    }
}

在我制作的 groovy 文件中测试 isAuthorized() 时,我注意到无论我如何安排它,我都无法将它实例化 TestResult result = get(resource) 为 null 以外的任何内容. isAuthorized() 调用另一个包含可能性的类中的枚举方法,否则只返回一个布尔值。

不过,这与重点无关。有没有一种有效的方法来模拟这个或强制 get(resource) 输出不为空的东西?或者,我可以直接将结果设置为特定值吗?

感谢您的帮助。整个过程令人难以置信的新事物,文档一直很棘手。

【问题讨论】:

  • 欢迎来到 SO。请通过提供MCVE 了解如何在此处提问。 SO 不是为了让你要求别人为你做你的工作,而是为了支持你解决你遇到的问题。为此,您需要展示您尝试过的内容并解释实际行为与预期行为有何不同。因为我们试图对新手友好,所以我给你一个免费的机会,我会回答这个问题。 ??????
  • 也显示你的测试用例
  • “有没有一种有效的方法来模拟这个或强制 get(resource) 输出不为空的东西?” - 是的。您希望看到其中哪一个的答案?
  • 请反馈。我回答了你的问题,但你既没有接受它是否足够,也没有发表评论。我觉得这不是特别礼貌。人们花时间帮助你,请不要忽视他们。

标签: java unit-testing inheritance groovy spock


【解决方案1】:

我给你看

  • 如何存根TestResult.isAuthorized 的结果以始终返回truefalse
  • 如何在真实的TestResultMap 实例上使用间谍,以便将get(_) 的结果存根,而类的其余部分行为正常(部分模拟),
  • 如何在不使用任何模拟的情况下测试您的类,因为如果测试中使用的方法没有做任何昂贵的事情,那么模拟可能根本不需要。或者,除了带有模拟依赖项的单元测试之外,您还想进行集成测试。

正在测试的类:

package de.scrum_master.stackoverflow.q70149644;

public class TestResult {
  private String result;

  public TestResult(String result) {
    this.result = result;
  }

  public boolean isAuthorized() {
    return !result.toLowerCase().matches(".*(forbidden|blocked|unauthorized|denied).*");
  }

  @Override
  public String toString() {
    return "TestResult(result='" + result + "')";
  }
}
package de.scrum_master.stackoverflow.q70149644;

import java.util.HashMap;

public class TestResultMap extends HashMap<String, TestResult> {
  private static final long serial = -1234567890L;

  public boolean isAuthorized(String resource) {
    TestResult result = get(resource);
    if (result == null) {
      throw new RuntimeException("Authorization not calculated");
    }
    return result.isAuthorized();
  }
}

Spock 规范:

package de.scrum_master.stackoverflow.q70149644

import spock.lang.Specification

class TestResultMapTest extends Specification {
  def "resource is authorized"() {
    given:
    TestResultMap map = new TestResultMap()
    TestResult testResult = Stub() {
      isAuthorized() >> true
    }
    map.put("resource", testResult)

    expect:
    map.isAuthorized("resource")
  }

  def "resource is unauthorized"() {
    given:
    TestResultMap map = new TestResultMap()
    TestResult testResult = Stub() {
      isAuthorized() >> false
    }
    map.put("resource", testResult)

    expect:
    !map.isAuthorized("resource")
  }

  def "resource not found"() {
    given:
    TestResultMap map = Spy() {
      get(_) >> null
    }

    when:
    map.isAuthorized("resource")

    then:
    def rte = thrown RuntimeException
    rte.message == "Authorization not calculated"
  }

  def "test without mocks"() {
    given:
    TestResultMap map = new TestResultMap()
    map.put("OK", new TestResult("Hello world"))
    map.put("not OK", new TestResult("Access denied"))

    expect:
    map.isAuthorized("OK")
    !map.isAuthorized("not OK")

    when:
    map.isAuthorized("foo")

    then:
    def rte = thrown RuntimeException
    rte.message == "Authorization not calculated"
  }
}

【讨论】:

    猜你喜欢
    • 2013-11-29
    • 2022-09-23
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 2019-08-29
    • 2016-09-27
    • 1970-01-01
    • 2017-06-29
    相关资源
    最近更新 更多