I am trying to write an unit test for a hadoop job. The catch is that the mapper uses the Context argument passed on to it in order to determine which file is being read by it at that moment. It makes the following call:
String inputFile = ((FileSplit) context.getInputSplit()).getPath().toString();
However, while writing a unit test for the mapper using MRUnit, I cant seem to find any way to mock out this Context object. Even MapDriver does not seem to have any option for setting a new Context object. Is there a way I can write a unit test for this mapper class?
MockInputSplit is what you need:
http://mrunit.apache.org/documentation/javadocs/0.9.0-incubating/org/apache/hadoop/mrunit/mock/MockInputSplit.html
Related
I am trying to write some JUnit tests for a set of methods which use some REST services on the web.
In general, within my methods, I am providing a filepath and a configuration as a parameter, but I expect things will get more complicated as I progress.
For right now, what are the best ways for me to write JUnit tests for the likes of :
public Answers changeFileToAnswer(String filePath, String mediaType) {
File document = new File(filePath);
Answers answers = restService.changeFileToAnswer(document, mediaType);
return answers;
}
What kind of Unit tests can I write for a simple class like this? Testing the answers object would be an integration tests, since an external call is made here, right? What is good practise here? Is there a way to mock the filepath being passed in as a parameter?
Notes -
This method is from a REST interface which will later be exposed through a GUI. I am currently testing it with POST calls from POSTman. Due to this, I am passing in a string for the filePath rather than a file object (as I could not post this to my server).
Thanks.
The test is not necessary to be integration. Your restService need to be mock or fake, so there is no real external call.
For mocking filePath you can use JUnit TemporaryFolder.
public class TestClass{
#Rule
private TemporaryFolder folder = new TemporaryFolder();
#Test
public void testMethod(){
File tempFile = folder.newFile("myfile.txt");
classUnderTest.changeFileToAnswer(file.getPath(), mediaType);
}
}
This rule will create a real file in file system which will be removed when tests finish execution.
UPD: You might also want to take a look at jimfs
Does it make sense to mock in unit test of a csv reader where we want to read the csv and put them into POJOs and make some queries? (specifically I mean mocking file read).
Let's assume the following example:
ICsvBeanReader beanReader = null;
beanReader = new CsvBeanReader(new FileReader(csvFileName),
CsvPreference.STANDARD_PREFERENCE);
String[] header = beanReader.getHeader(true);
Book bookBean = null;
while ((bookBean = beanReader.read(Book.class, header,
processors))!= null) {
books.add(bookBean);
}
Thank you in advance.
This seems like a good idea - it can decouple your unit being tested from your implementation of read(). That way if you change to a different library to read the files, your unit tests don't all have to be rewritten.
Strictly speaking, a unit test is designed to test the functionality of a piece of code, rather than the integration of code with an external part of the program. Testing the functionality of reading an actual file would be an integration test, rather than a unit test. An integration test is important too, because you want to make sure that your file reader can function on actual files. But for the purpose of ensuring that the code runs, you can also create a unit test.
To create a unit test, you can mock the file reader object to return a dummy response (byte[] or whatever type the interface provides). Then you can populate your POJOs and do your assertions that everything behaves as expected.
So to summarize, both an integration test and a unit test might be a good idea, but a unit test will allow you to isolate and test the logic of your code.
Update:
To take your updated code sample into account, I would go about mocking the CsvBeanReader like this:
ICsvBeanReader mockedBeanReader = mock(CsvBeanReader.class);
Book book1 = new Book();
Book book2 = new Book();
Book book3 = new Book();
when(mockedBeanReader.getHeader(true))
.thenReturn(new String[]{"here", "is", "header"});
when(mockedBeanReader.read(Book.class, header, processors))
.thenReturn(book1)
.thenReturn(book2)
.thenReturn(book3);
And now you have a fully mocked CsvBeanReader object. You can perform assertions on your POJOs and verify that the business logic of your code be correct.
I've read a couple of answers online but none of them seem to work for me.
This is what I have in my #Setup method:
MockitoAnnotations.initMocks(this);
Configuration mConfiguration = Mockito.mock(Configuration.class);
mConfiguration.locale = Locale.US;
when(mContext.getResources().getConfiguration()).thenReturn(mConfiguration);
when(StorageUtils.getUserAgent(mContext)).thenReturn("User-Agent: Android Unit Test");
when(mContext.getResources().getString(R.string.service_domain)).thenReturn("testString");
All of it works, except the last line getString. Ideally the string would be from the actual strings resource I already have for the whole app, but if that's not possible, I can add it to this line manually.
The part that doesn't work is when I try to call the string.
The .getString(R.string.service_domain) part is getting called in another method (the method used in the actual application) as part of the context.
So my method is called like this from unit test:
Utils.getProductImageUrl(mContext, product);
And this getProductImageUrl does this:
productImageUrl = context.getString(R.string.service_domain) + baseImageUrl;
When I run the unit test, the productImageUrl variable get a full url of
null/123.png
How can I mock the string so it can be passed as part of the context to my method?
Let me know if you need additional information.
Thank you.
I've set up a JMock context in my JUnit #Before test, something like:
context.checking(new Expectations()
{
{
allowing(mockPayload).getContent();
will(returnValue(FileUtils.readFileToByteArray(XML_FILE)));
}
});
This reads in an xml file and does some tests on it's content. Later on in the test I want to read in a different file and do similar tests. Is there anyway to do this without creating a new 'context', ie, by re-using the context to read in a different file. I know that Junit doesn't guarantee the order of the tests you carry out, so trying to reuse a context that might not have been used yet is going to cause an error. Any ideas?
I would like to run a specific JUnit test method programmatically. I know I can run the whole test using the following code snippet:
Class<?> test = Class.forName("MyTestClass");
JUnitCore junit = new JUnitCore();
Result result = junit.run(test);
However, I would like to run a specific method within this test class which contains multiple methods.
It would also be fantastic if I could control the setUp/tearDown behaviour.
Thank you
There's an overloaded JUnitCore#run method version that accepts Request. While Request has Request#method factory method to:
Create a Request that, when processed, will run a single test. This is
done by filtering out all other tests. This method is used to support
rerunning single tests.
If you need to control #setUp / #tearDown (i.e., methods marked with #Before and/or #After annotations) you can extend the class and override methods you need to alter.