4

EDIT: The method I'm testing calls this constant that's defined in another class, so I want to test that th emethod works independently of how the other class defines the constant. Mocking it was the first thing I could think of, but I'm open to other ideas for how to test it in a clean, secure way

(Class, method, and variable names are genericized)

I'm trying to figure out how to write a test. One of my methods gets a constant from another class, like so:

OtherClass.CONSTANT

and this constant is defined as:

public static final List<Long> CONSTANT =
  ImmutableList.of(1, 2);

In the test for this method, I want to mock this call. I've tried

when(OtherClass.CONSTANT).thenReturn(ImmutableList.of(1, 2));

but that gives me this error:

RegularImmutableList cannot be returned by otherFunction()
otherFunction() should return String

otherFunction() being some other function in the code base that doesn't seem to be related to anything I've been working on.

I've also tried

doReturn(ImmutableList.of(1, 2)).when(OtherClass.CONSTANT);

but, as you might be guessing, it gives me this error:

Argument passed to when() is not a mock!
Example of correct stubbing:
doThrow(new RuntimeException()).when(mock).someMethod();

I'm pretty lost as to how exactly I should be mocking this constant.

HLH
  • 1,097
  • 4
  • 15
  • 22
  • What type is `OtherClass.CONSTANT`? – Lorelorelore Jan 08 '19 at 19:01
  • how is OtherClass.CONSTANT declared ? private ? final? static? – pvpkiran Jan 08 '19 at 19:08
  • 2
    why do you want to mock a constant? – Phil Ninan Jan 08 '19 at 19:16
  • you can't mock static things with mockito (only), you need PowerMock(ito) ...https://stackoverflow.com/a/21116014/592355 – xerx593 Jan 08 '19 at 19:22
  • A constant is a constant. You don't need to do anything to mock it: it's already defined. Mocks are only for when then thing you actually need to test it too hard to construct in tests. – Andy Turner Jan 08 '19 at 19:23
  • The method I'm testing calls this constant that's defined in another class, so I want to test that it works independently of how the other class defines the constant. Mocking it was the first thing I could think of, but I'm open to other ideas for how to test it in a clean, secure way – HLH Jan 08 '19 at 19:27

1 Answers1

5

As you've discovered, you can't mock the value of a constant.

Likely the easiest method would be to convert your design to use an interface to supply the value, rather than using the value directly.

Something like:

interface ConstantSupplier {
    List<Long> get();
}

public MyClass(ConstantSupplier supplier) {
    this.supplier = supplier;
}

Then you would replace references to the constant to supplier.get().

This is now easy to mock:

ConstantSupplier supplier = mock(ConstantSupplier.class);
when(supplier.get()).thenReturn(List.of(4L, 9L));

Your non-mocked code could use a lambda to supply the real value:

obj = new MyClass(() -> OtherClass.CONSTANT);
sprinter
  • 27,148
  • 6
  • 47
  • 78