I have the following class
public class Multiplier {
private static Map<Integer, Float> map;
private static final float DEFAULT_MULTIPLIER = 4.4F;
static {
// This map is actually populated by reading from a file. This is an example on how the map looks like.
map = new HashMap<>();
map.put(1, "3.5F");
map.put(2, "5.8F");
map.put(3, "2.7F");
}
public static float getMultiplier(Integer id) {
return map.getOrDefault(id, DEFAULT_MULTIPLIER);
}
}
I have another class
public class MultiplierUser {
private integer id;
private float value;
private float result;
public MultiplierUser(int id, float value) {
this.id = id;
this.value = value;
}
public void setResult() {
result = value * Multiplier.getMultiplier(this.id);
}
public float getResult() {
return this.result;
}
}
What's the best way to test this method?
Should I get the expected value by calling the method and then asserting?
public testMethod() {
MultiplierUser multiplierUser = new MultiplierUser(1, 10F);
multiplierUser.setResult();
float expected = Multiplier.getMultiplier(1) * 10F;
Assert.assertEquals(expected, multiplierUser.getResult());
}
Or mock?
public testMethod() {
MultiplierUser multiplierUser = new MultiplierUser(1, 10F);
Mockito.mock(Multiplier.class);
when(mock.getMultiplier(1)).thenReturn(1.5F);
multiplierUser.setResult();
float expected = 1.5F * 10F;
Assert.assertEquals(expected, multiplierUser.getResult());
}
I can't understand which would be the better way to test this method? If I use the former, I'm basically calling the method myself and getting the result. But if there's an issue with the method in the future, the test will keep succeeding. If I'm using a mock, then I'm technically not testing the method and the value it returns. I'm confused. Please help.
CodePudding user response:
To test the setResult
method, mocking the Multiplier
is sufficient.
The methods setResult
and getMultiplier
are pretty straight forward in this case.
But let's consider a scenario where complex operations are involved:
public class A {
public int foo1() {
//some complex operations
}
}
public class B {
public int foo2() {
A a = new A();
int val = a.foo1();
//some complex operations
}
}
Now to test foo2()
, it makes more sense to mock the class A
and use thenReturn
to get some sample output rather than testing the entire foo1()
method in the test for foo2()
. This ensures that you are only testing the corresponding units of code pertaining to the method under test.
Unit tests should be designed such that they are simple, readable and deals with one logic at a time.