1

I am using creating an application using mapreduce2 and testing the same using MRUnit 1.1.0. In one of the tests, I am checking the output of a reducer which puts the 'current system time' in it's output. I.e. at the time the reducer executes, the timestamp is used in context.write() to be written along with the rest of the output. Now even though I use the same method to find the system time in the test method as the one I use in the reducer, the times calculated in both are generally a second apart, like 2016-05-31 19:10:02 and 2016-05-31 19:10:01. So the output in the two turns out to be different, example:

test_fe01,2016-05-31 19:10:01
test_fe01,2016-05-31 19:10:02

This causes an assertion error. I wish to ignore this difference in timestamps, so the tests pass if the rest of the output apart from the timestamp is matched. I am looking for a way to mock the method used for returning the system time, so that a hardcoded value is returned, and the reducer and the test both use this mocked method during the test. Is this possible to do? Any help will be appreciated.

Best Regards

EDIT: I have already tried Mockito's spy functionality in the my test:

 MClass mc = Mockito.spy(new MClass());
 Mockito.when(mc.getSysTime()).thenReturn("FakeTimestamp");

However, this gives a runtime error:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.

The method getSysTime() is public and static and class MClass is public and doesn't have any parent classes.

Ankit Khettry
  • 997
  • 1
  • 13
  • 33

1 Answers1

1

Assuming i understand your question, you could pass a time into the Reduce using the configuration object. In your reduce you could check if this configuration is set and use it, otherwise you use the system time.

This way you can pass in a known value for testing and assert you get that same value back.

Binary Nerd
  • 13,872
  • 4
  • 42
  • 44
  • Sounds like a solution, but is it not possible to do so without adding any code to the reducer? I would like to mock the `String getSysTime()` method that is implemented in my application (and which returns the current system time), in my test so that this method returns a hardcoded timestamp. – Ankit Khettry Jun 01 '16 at 13:22
  • You could extend your reducer and override that method or perhaps use something like Mockito to mock that specific method: http://stackoverflow.com/questions/14970516/use-mockito-to-mock-some-methods-but-not-others – Binary Nerd Jun 01 '16 at 13:39
  • The method is not in my reducer class and there is a lengthy chain of calls through which the timestamp is returned. The question I have posted has a lot of abstractions and simplifications. The configuration solution would also require me to add a Configuration object to the parameter list of all methods involved in the chain. The solution might work out but would cause a lot of unwanted complexitities and regression. An ideal solution in my case would be to mock that one particular method of that one particular class in my test, but I am not sure how it is to be achieved. – Ankit Khettry Jun 01 '16 at 13:45