In my code I have something like this:
private void doSomething() {
Calendar today = Calendar.getInstance();
....
}
How can I "mock" it in my junit test to return a specific date?
You can mock it using PowerMock in combination with Mockito:
On top of your class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassThatCallsTheCalendar.class})
The key to success is that you have to put the class where you use Calendar in PrepareForTest instead of Calendar itself because it is a system class. (I personally had to search a lot before I found this)
Then the mocking itself:
mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);
As far as I see it you have three sensible options:
Inject the Calendar instance in whatever method/class you set that day in.
private void method(final Calendar cal)
{
Date today = cal.getTime();
}
Use JodaTime instead of Calendar. This is less an option and more a case of a suggestion as JodaTime will make your life a lot easier. You will still need to inject this time in to the method.
DateTime dt = new DateTime();
Date jdkDate = dt.toDate();
Wrap Calendar inside some interface that allows you to fetch the time. You then just mock that interface and get it to return a constant Date.
Date today = calendarInterfaceInstance.getCurrentDate()
Don't mock it - instead introduce a method you can mock that gets dates. Something like this:
interface Utility {
Date getDate();
}
Utilities implements Utility {
public Date getDate() {
return Calendar.getInstance().getTime();
}
}
Then you can inject this into your class or just use a helper class with a bunch of static methods with a load method for the interface:
public class AppUtil {
private static Utility util = new Utilities();
public static void load(Utility newUtil) {
this.util = newUtil;
}
public static Date getDate() {
return util.getDate();
}
}
Then in your application code:
private void doSomething() {
Date today = AppUtil.getDate();
....
}
You can then just load a mock interface in your test methods.
#Test
public void shouldDoSomethingUseful() {
Utility mockUtility = // .. create mock here
AppUtil.load(mockUtility);
// .. set up your expectations
// exercise the functionality
classUnderTest.doSomethingViaAPI();
// ... maybe assert something
}
See also Should you only mock types you own? and Test smell - everything is mocked
Using Mockito and PowerMockito:
Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);
Refer to the link for the complete code.
Write a class called DateHelper with a method getCalendar that returns Calendar.getInstance(). Refactor the class that you're testing so that it has a member variable of type DateHelper, and a constructor that injects that member variable. Use that constructor in your test, to inject a mock of DateHelper, in which getCalendar has been stubbed to return some known date.
You can mockit using JMockit. Here you can see how you can do it: Mock Java Calendar - JMockit vs Mockito.
Avoid use Calendar.getInstance() and just use Mockito methods to return what you like.
For example:
#Test
fun italianLocale_returnsItalianFormatDate() {
val calendar: Calendar = Mockito.mock(Calendar::class.java)
Mockito.`when`(calendar.get(Calendar.DAY_OF_MONTH)).thenReturn(27)
Mockito.`when`(calendar.get(Calendar.YEAR)).thenReturn(2023)
Mockito.`when`(calendar.get(Calendar.MONTH)).thenReturn(1)
val formatted = calendar.toReadableDate()
assert(formatted == "27/01/2023")
}
import Mockito in your gradle file with:
testImplementation ("org.mockito.kotlin:mockito-kotlin:x.x.x")
or (if you are using groovy)
testImplementation "org.mockito.kotlin:mockito-kotlin:x.x.x"
Related
I have a code where I calculate the difference between current clock time and time saved in my db
If difference between the two is greater than certain value then I return result accordingly.
For this case I am trying to write test but is facing problem to mock Clock.millis(). I have referred some answers but none worked for me can someone help me with that.
For my test I want to mock this clock.millis() function with a fixed value so that each time I run test it takes that value only.
A Clock is meant for providing access to the current instant, date and time using a time-zone. You don't really need to mock it. As your class needs to obtain the current instant, so it should receive an instance of the Clock in the constructor:
public class FooService {
private final Clock clock;
public FooService(Clock clock) {
this.clock = clock;
}
public boolean isLocked() {
long differenceInSecond = (clock.millis() - this.getLockedAt()) / 1000;
return differenceInSecond < 7200;
}
private long getLockedAt() {
...
}
}
Then, in your test, you can use a fixed() clock, which will always return the same instant:
#Test
public void isLocked_shouldReturnTrue_whenDifferenceInSecondIsSmallerThan7200() {
// Create a fixed clock, which will always return the same instant
Instant instant = Instant.parse("2020-01-01T00:00:00.00Z");
Clock clock = Clock.fixed(instant, ZoneOffset.UTC);
// Create a service instance with the fixed clock
FooService fooService = new FooService(clock);
// Invoke the service method and then assert the result
boolean locked = fooService.isLocked();
assertThat(locked).isTrue();
}
In a Spring Boot application, you could expose a Clock as a #Bean:
#Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
And then Spring will take care of injecting it into your service:
#Service
public class FooService {
private final Clock clock;
public FooService(Clock clock) {
this.clock = clock;
}
...
}
You need to wrap Clockinto your own class, exposing Clock.millis() as a delegate. In your test you can then mock your wrapper and return whatever you like.
I have encountered a problem when I was tasked with creating JUnit test to one of my camel processor.
The main class is as follows: (redundant things omitted).
#Stateless
#Named
public class CalculateProportionalAmount implements Plugin{ // where Plugin is our interface extending a Processor
LocalDate now;
#Override
public void process(final Exchange exchange) throws Exception{
now = getNow();
int startDay = getValueOfInputParameter("start") //just gets 1-31 from input parameters on exchange
int value = getValueOfInputParameter("value") //gets value from input parameters
/*
More kind-of irrelevant lines of code. Idea is that the processor calculates number of days between "now" and startDay, calculates what proportion of month this amount of days is and applies this proportion to the value.
So if today would be 1st and startDay is 10th (so 10 days between) when September has 30 days and value = 1000, the processor would calculate (10/30)*1000
*/
}
public LocalDate getNow(){
return LocalDate.now();
}
}
And for the test class:
public class CalculateProportionalAmountTest{
Plugin plugin;
#Before
public void setUp(){
//inicialize parameter maps, instantiate the plugin, so that we can reference it. "plugin" value is then instance of the "CalculateProportionalAmount" class.
}
#Test
public void pluginTestNextMonth() throws Exception {
Mockito.when(((CalculateProportionalAmount) plugin).getNow()).thenReturn(LocalDate.of(2017, 12, 11)); //obviously does not work, because plugin is not mocked....
ruleParameter.put("start", "10"); //here we set the "start" param that processor class gets.
ruleParameter.put("value", "1000"); //here we set the "value" param that processor class gets.
Exchange prepareInput = prepareExchange(scenarioParameters, ruleParameter);
Exchange output = execute(prepareInput);
String resultString = getScenarioParameterByKey(output, "result");
TestCase.assertEquals(String.format("%.6f", Double.valueOf(1000) * 30 / 31), resultString); //obviously will not pass unless on 11th of December
}
}
My biggest problem is that the getNow() method is and has to be called inside the process method, overwriting any attempts to specify a date.
Calculating the "real" proportions is also not viable option as we need to be able to check for variants "later this month", "earlier this month" and "today" on any day.
As the most feasible solution I now have is to rig (mock) the getNow() method to return a specific date when called from the test, but I need to leave the process method to be working as written, without any mocks.
The project this is part of already uses Mockito, but I am not very skilled in how it works and how to correctly mock the class so that it works as described above. I already made an attempt to do so in the beginning of the test class, but it currently ends in exception and I have been browsing tutorials since without much luck.
Thank you for help
You can use #Spy i think.
#Spy
Plugin plugin;
And then in your test method you can manipulate with doReturn for this public method
Mockito.doReturn(LocalDate.of(2017, 12, 11)).when((CalculateProportionalAmount) plugin).getNow();
#Spy tag refer to real object and you can change the return methods of spy object.
Mockito offers partial mocks to mock methods like getNow and call the real implementation for other methods.
In order to test camel route properly you should extend CamelTestSupport class from camel package. In general, they provide a support for testing camel.
My advice is to create custom route:
#Override
protected RoutesBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() {
from( "direct:testRoute" )
.process( new YourPluginClass() )
.end();
}
};
}
Then, you will be able to call it with fluentTemplate from CamelTestSupport class and test processor properly.
In order to mock behaviour of processor (partially) use spy from Mockito as #drowny said. Keep it mind that if you want to use #Spy annotation you have to init it with MockitoAnnotations.initMocks(this) line in #Before set up method.
Because I can't fake an abstract class directly and I know the implementing class, I added the fake to the implementing class.
#BeforeClass
public static void fakeCurrentYear() {
// Mocking the abstract 'Calender' does not work, see: https://github.com/jmockit/jmockit1/issues/71
// So we use the implementing class 'GregorianCalendar'.
new MockUp<GregorianCalendar>() {
#Mock public int get(Invocation invocation, int field) {
return 2016;
}
};
}
I'm using jMockit v 1.31 with JUnit 4.12 and Maven 3.x.
When I execute tests individually, everything is fine.
But when I execute all tests together, another test fails because the log4jlogger in the implementing class obviously uses the fake-implementation.
I think this is because previously GregorianCalendar did not overwrite that method. However, I thought the fake is automatically removed after the testclass! Is this a bug?
Can I remove it manually? I've tried stepping back to JMockit v1.25, created a static variable yearMock = new MockUp<GregorianCalendar>() ... and calling yearMock.tearDown() in a #AfterClass method, but it didn't change anything.
I've used a workaround, where I created a method in the class under test with just a single line of code
private int currentYear4digits() {
return Calendar.getInstance().get(Calendar.YEAR);
}
In my test I then mocked this method.
#BeforeClass
public static void fakeCurrentYear() {
new MockUp<MyClass>() {
#Mock
public int currentYear4digits() {
return 2016;
}
};
}
However, this is just a workaround. It would be cumbersome if the calls to Calendar where made from several classes.
I was playing with org.springframework.data.jpa.domain.Specifications, it's just a basic search :
public Optional<List<Article>> rechercheArticle(String code, String libelle) {
List<Article> result = null;
if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(libelle)){
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
}else{
if(StringUtils.isNotEmpty(code)){
result= articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)));
}else{
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteLibelle(libelle)));
}
}
if(result.isEmpty()){
return Optional.empty();
}else{
return Optional.of(result);
}
}
And that's actually working fine but I'd like to write unit tests for this method and I can't figure out how to check specifications passed to my articleRepository.findAll()
At the moment my unit test looks like :
#Test
public void rechercheArticle_okTousCriteres() throws FacturationServiceException {
String code = "code";
String libelle = "libelle";
List<Article> articles = new ArrayList<>();
Article a1 = new Article();
articles.add(a1);
Mockito.when(articleRepository.findAll(Mockito.any(Specifications.class))).thenReturn(articles);
Optional<List<Article>> result = articleManager.rechercheArticle(code, libelle);
Assert.assertTrue(result.isPresent());
//ArgumentCaptor<Specifications> argument = ArgumentCaptor.forClass(Specifications.class);
Mockito.verify(articleRepository).findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
//argument.getValue().toPredicate(root, query, builder);
}
Any idea?
I was having almost the same problems as you had, and I changed my class that contains Specifications to be an object instead of just one class with static methods. This way I can easily mock it, use dependency injection to pass it, and test which methods were called (without using PowerMockito to mock static methods).
If you wanna do like I did, I recommend you to test the correctness of specifications with integration tests, and for the rest, just if the right method was called.
For example:
public class CdrSpecs {
public Specification<Cdr> calledBetween(LocalDateTime start, LocalDateTime end) {
return (root, query, cb) -> cb.between(root.get(Cdr_.callDate), start, end);
}
}
Then you have an integration test for this method, which will test whether the method is right or not:
#RunWith(SpringRunner.class)
#DataJpaTest
#Sql("/cdr-test-data.sql")
public class CdrIntegrationTest {
#Autowired
private CdrRepository cdrRepository;
private CdrSpecs specs = new CdrSpecs();
#Test
public void findByPeriod() throws Exception {
LocalDateTime today = LocalDateTime.now();
LocalDateTime firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
List<Cdr> cdrList = cdrRepository.findAll(specs.calledBetween(firstDayOfMonth, lastDayOfMonth));
assertThat(cdrList).isNotEmpty().hasSize(2);
}
And now when you wanna unit test other components, you can test like this, for example:
#RunWith(JUnit4.class)
public class CdrSearchServiceTest {
#Mock
private CdrSpecs specs;
#Mock
private CdrRepository repo;
private CdrSearchService searchService;
#Before
public void setUp() throws Exception {
initMocks(this);
searchService = new CdrSearchService(repo, specs);
}
#Test
public void testSearch() throws Exception {
// some code here that interact with searchService
verify(specs).calledBetween(any(LocalDateTime.class), any(LocalDateTime.class));
// and you can verify any other method of specs that should have been called
}
And of course, inside the Service you can still use the where and and static methods of Specifications class.
I hope this can help you.
If you are writing Unit Tests then you should probably mock the call to findAll() method of articleRepository Class using a mocking framework like Mockito or PowerMock.
There is a method verify() using which you can check if the mock is invoked for the particular parameters.
For Example, if you are mocking the findAll() method of articleRepository Class and want to know if this method is called with particular arguments then you can do something like:
Mokito.verify(mymock, Mockito.times(1)).findAll(/* Provide Arguments */);
This will fail the test if mock has not been called for the arguments that you provided.
Your problem is that you are doing too many things within that one method. You should have three different methods that work on articleRepository.
Then you can use mocking as the others suggest:
setup your mocks so that you know which call on articleRepository should be made
verify that exactly the expected calls are happening
Please note: these three methods should be internal; the main point there is: you can't test this method with ONE call from the outside; as it is doing more than one thing, depending on the input that you provide. Thus you need to create at least one test method for each of the potential paths in your code. And that becomes easier (from a conceptual point of view) when you separate your code into different methods.
public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}