0

In our codebase, we use a specific class map which stores the results for authorization requests including whether or not someone has the auth to get in.

Currently writing some unit tests (a thing I have little practice on) that contains this, a modified version of our code for you to look at:

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();
    }
}

When testing the isAuthorized() in the groovy file I had made, I've noticed that no matter how I have it arranged, I can not get it to instantiate TestResult result = get(resource) to be anything other than null. isAuthorized() calls upon an enum method in another class that contains the possibilities, but otherwise just returns a boolean.

That's tangential to the point, though. Is there an efficient way to mock this or force get(resource) to output something not null? Alternatively, can I directly set result to a particular value?

Thanks for any help. Incredibly new to this whole process and documentation has been tricky.

vidyadawg
  • 1
  • 1
  • 1
    Welcome to SO. Please learn how to ask questions here by providing an [MCVE](https://stackoverflow.com/help/mcve). SO is not meant for you to ask others to do your work for you but to support you in fixing problems you have. In order to do that, you need to show what you tried and explain how the actual behaviour differs from the expected one. Because we try to be friendly to newbies, I give you one free shot and am going to answer this question. – kriegaex Nov 29 '21 at 08:44
  • show your test case as well – injecteer Nov 29 '21 at 11:57
  • "Is there an efficient way to mock this or force get(resource) to output something not null?" - Yes. Which of those would you like to see an answer for? – Jeff Scott Brown Nov 29 '21 at 19:53
  • Feeback, please. I answered your question, but neither did you accept it if it was adequate nor did you comment on it. I do not find that particularly polite. People are spending time in order to help you, please do not ignore them. – kriegaex Dec 05 '21 at 04:32

1 Answers1

1

I am showing you

  • how to stub the result of TestResult.isAuthorized to always return true or false,
  • how to use a spy on a real TestResultMap instance in order to stub the result of get(_) with the rest of the class behaving normally (partial mocking),
  • how to test your class without using any mocks, because if the methods used in the test are not doing anything expensive, mocking might not be necessary at all. Or maybe you want to also have an integration test in addition to the unit test with mocked dependencies.

Classes under test:

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 specification:

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"
  }
}
kriegaex
  • 63,017
  • 15
  • 111
  • 202