-1

how to mock following code? i dont want to change my code.

Date date = new Date();
String res_timestamp=new Timestamp(date.getTime()).toString();

my code:

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("PST"));
    Date NOW = sdf.parse("2019-02-11 00:00:00");
    Timestamp time=new Timestamp(NOW.getTime());
    whenNew(Timestamp.class).withNoArguments().thenReturn(time);

how can i mock it? am finding hard to mock it.

how can i solve it?

note: i do not want to change my code. without changing my code i have to mock those two lines.

karthick S
  • 51
  • 1
  • 2
  • 9
  • I recommend you don’t use `SimpleDateFormat`, `Date` and `Timestamp`. Those classes are poorly designed and long outdated, the first in particular notoriously troublesome. Instead use either `LocalDate` or `Instant` and `DateTimeFormatter`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Feb 11 '19 at 12:03
  • 2
    It is unclear what you are asking for; I suggest you look into https://stackoverflow.com/questions/24491260/mocking-time-in-java-8s-java-time-api ... the best thing to do in 2019 is to look into the `Clock` class. And yes, forget about Date and all that stuff. That is ancient past. – GhostCat Feb 11 '19 at 12:03
  • Possible duplicate of [Writing and testing convenience methods using Java 8 Date/Time classes](https://stackoverflow.com/questions/52956373/writing-and-testing-convenience-methods-using-java-8-date-time-classes). Not an exact duplicate of what you asked, but could still give you and other readers what you all want. – Ole V.V. Feb 11 '19 at 12:07
  • guys, as mentioned earlier, i do not want to change my code. i would like to mock those two lines in my test cases rather than changing my code. – karthick S Feb 11 '19 at 12:28
  • 2
    Possible duplicate of [Override Java System.currentTimeMillis for testing time sensitive code](https://stackoverflow.com/questions/2001671/override-java-system-currenttimemillis-for-testing-time-sensitive-code) – M. Prokhorov Feb 11 '19 at 12:46
  • 3
    What above says. But I'm just going to reiterate again: I would rather you change your code. – M. Prokhorov Feb 11 '19 at 12:46
  • In that case you HAVE TO refactor your code, and it's ok. I would recommend you to read more about unit testing and how it's connected with the code refactoring (for example, Roy Osherove's "The art of unit testing") – amseager Feb 20 '19 at 00:00

1 Answers1

2

tl;dr

  • Use java.time.Clock, ZonedDateTime, Instant, ZoneId.
  • Inject an altered Clock object as a dependency: Clock.fixed( … ).
  • Never use Date, Calendar, SimpleDateFormat, Timestamp, TimeZone.

Pass an altered Clock object as a dependency

You are using terrible date-time classes that were supplanted years ago by the java.time classes defined by JSR 310.

The java.time.Clock class offers several alternate behaviors suitable for testing. These included a fixed point in time, altered cadences, and and adjustment from the current moment.

Pass one of these Clock objects to the various methods in the java.time classes for your testing purposes.

PST is not a time zone. Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;

Build up the specific moment you have in mind for your testing.

LocalDate ld = LocalDate.of( 2019 , 2 , 11 ) ;
LocalTime lt = LocalTime.MIN ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

zdt.toString(): 2019-02-11T00:00-08:00[America/Los_Angeles]

Calling Clock.fixed requires an Instant, a moment in UTC. We can adjust from our zoned value to UTC by extracting an Instant. Same moment, same point on the timeline, different wall-clock time.

Instant instant = zdt.toInstant() ;

instant.toString(): 2019-02-11T08:00:00Z

Specify a Clock that forever reports the current moment as that specific moment, without incrementing.

Clock clock = Clock.fixed( instant , z ) ;

clock.toString(): FixedClock[2019-02-11T08:00:00Z,America/Los_Angeles]

Inject the fixed clock as a dependency.

Instant now = Instant.now( clock ) ;  // Tell me a lie.

now.toString(): 2019-02-11T08:00:00Z

See this code run live at IdeOne.com.

JDBC 4.2

If you were instantiating java.sql.Timestamp for use with a database, instead use the java.time classes. As of JDBC 4.2, we can exchange java.time objects with a database.

Your JDBC driver might have optional support for Instant.

myPreparedStatement.setObject( … , instant ) ;            // Storing data.
Instant instant = myResultSet.get( … , Instant.class ) ;  // Retrieving data.

Your driver must support OffsetDateTime.

myPreparedStatement.setObject( … , instant.atOffset( ZoneOffset.UTC ) ) ;            // Storing data.
OffsetDateTime odt = myResultSet.get( … , OffsetDateTime.class ) ;  // Retrieving data.

Adjust into a time zone.

ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154