Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a class I am adding unit tests to. The class has several constructors which take different types and converts them into a canonical form, which can then be converted into other types.

public class Money {
    public Money(long l) {
        this.value = l;
    }

    public Money(String s) {
        this.value = toLong(s);
    }

    public long getLong() {
        return this.value;
    }

    public String getString() {
        return toString(this.value);
    }
}

In reality there are a couple of other types it accepts and converts to.

I am trying to work out what the most appropriate way to test these constructors is.

Should there be a test per-constructor and output type:

@Test
public void longConstructor_getLong_MatchesValuePassedToConstructor() {
    final long value = 1.00l;

    Money m = new Money(value);
    long result = m.getLong();

    assertEquals(value, result);
}

This leads to a lot of different tests. As you can see, I'm struggling to name them.

Should there be multiple asserts:

@Test
public void longConstructor_outputsMatchValuePassedToConstructor() {
    final long longValue = 1.00l;
    final String stringResult = "1.00";

    Money m = new Money(longValue);

    assertEquals(longValue, m.getLong());
    assertEquals(stringResult, m.getString());
}

This has multiple asserts, which makes me uncomfortable. It is also testing getString (and by proxy toString) but not stating that in the test name. Naming these are even harder.

Am I going about it completely wrong by focussing on the constructors. Should I just test the conversion methods? But then the following test will miss the toLong method.

@Test
public void getString_MatchesValuePassedToConstructor() {
    final long value = 1.00;
    final String expectedResult = "1.00";

    Money m = new Money(value);
    String result = m.getLong();
    assertEquals(expectedResult, result);
}

This is a legacy class and I can't change the original class.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
84 views
Welcome To Ask or Share your Answers For Others

1 Answer

It looks like you've got a canonical way of getting the "raw" value (toLong in this case) - so just test that all the constructors are correct when you fetch that value. Then you can test other methods (such as getString()) based on a single constructor, as you know that once the various constructors have finished, they all leave the object in the same state.

This is assuming somewhat white-box testing - i.e. you know that toLong is really a simple reflection of the internal state, so it's okay to test that + a constructor in a test.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...