Home > Net >  Best way to unit test this method?
Best way to unit test this method?

Time:01-21

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.

  • Related