1

My team received a new project. The project has a bunch of tests which do not pass. By their words, all the tests should pass. After investigating the problem I discovered that there is a common issue. Most of the failing tests create Timestamp and work with it but the expected and the actual date is not the same. The difference is exactly one hour. The old dev team has been working from a zone which is GMT + 1 and we are working from GMT + 2.

Why this may happen?

EDIT:

I have a test which creates entity Rating and sets a bunch of properties. For example:

rating.setValidFromDate(new Timestamp(1459841866798L));

then the test assert an expected String constant and rating.toString()

As I said the difference is exactly 1 hour

EDIT 2:

@Test
public void testToString() {
    Rating rating = new Rating();
    rating.setValidFromDate(new Timestamp(1459841866798L));

    assertEquals("Rating{validFromDate='2016-04-05 09:37:46'}", rating.toString());
}

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(Rating.class.getSimpleName());
    builder.append("{");
    builder.append("validFromDate='" + DateHelper.getStringFromDate(validFromDate) + "'");
    builder.append("}");
    return builder.toString();
}

public static String getStringFromDate(Date dateValue) {
    String strDate = "";
    if (dateValue != null) {
        DateFormat dateFormat = new SimpleDateFormat(Constants.DATETIME_FORMAT);
        strDate = dateFormat.format(dateValue);
    }
    return strDate;
}

Solved

I decided to give you my solution to this problem.

After reading this: java.sql.Timestamp: changing timezone of Timestamp I found a way to manipulate time zone of the tests. So I decided to write a JUnit rule which will do this to all of my tests.

I have written the following Statement:

public class GermanTimeZoneStatement extends Statement {

    private final Statement base;

    public GermanTimeZoneStatement(Statement base) {
        super();
        this.base = base;
    }

    @Override
    public void evaluate() throws Throwable {
        TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
        base.evaluate();
    }
}

After that I've written this rule:

public class GermanTimeZoneRule implements TestRule {

    public static GermanTimeZoneRule getInstance() {
        return new GermanTimeZoneRule();
    }

    @Override
    public Statement apply(Statement base, Description description) {
        return new GermanTimeZoneStatement(base);
    }
}

Finally I've include the rule in my tests like this:

    @Rule
    public GermanTimeZoneRule germanTimeZoneRule = GermanTimeZoneRule.getInstance();
Community
  • 1
  • 1
Petar Petrov
  • 586
  • 2
  • 10
  • 28
  • 7
    I guess the answer is in the code – Scary Wombat Jul 04 '17 at 08:04
  • Probably they compared Timestamps as strings instead of comparing them as Timestamps. Timestamp have both `equals()` and `compareTo()` methods. So you probably have to rewrite some code to use these methods. – Balázs Nemes Jul 04 '17 at 08:16
  • Well, you are almost there. You know whats causing the issue. Now go on and check if the first or the second date is the wrong date and fix how it is created. Another option might be to rent a build server in the GMT+1 region ;) – lupz Jul 04 '17 at 08:17
  • 1
    Can you show us an example of a test that's failing? Or do we just have to guess what the code looks like? – Dawood ibn Kareem Jul 04 '17 at 08:18
  • You may or may not want to bother right now, but the good solution would involve throwing out the outdated classes `Timestamp`, `DateFormat` and `SimpleDateFormat` and instead using the modern classes `Instant`, `DateTimeFormatter` and friends. They are nicer and smoother to work with, not least when debugging, so I suggest you give it a thought. – Ole V.V. Jul 04 '17 at 15:13
  • This is funny IMHO. You said the old dev team was working at GMT+1. However, the timestamp of 1459841866798L from your test agrees with a time of `2016-04-05T09:37:46.798+02:00`, that is, at GMT+2, your time zone offset. Also I’m a bit confused about the use of valid *from* and valid *to*. – Ole V.V. Jul 04 '17 at 15:27

1 Answers1

3

The code that you're testing is time-zone dependent. It outputs a particular date according to what time it is in the user's default time-zone. That's why it gives you different output from what it gives your colleagues.

You need to go back to the specification for that code, and check whether that's the intended behaviour. If it is, you'll need to modify the test to take the time-zone into account. If it's not the intended behaviour, then congratulations, your test has exposed a bug!

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110