Mock any objects of a class - java

How can I mock any objects of a class.
What I want is for any file object to return true when exists() is called on it.
Something like:
Mockito.mock(File.class)
//return true for any object of File that calls exist()
File file = new File("thisDoesntExist");
assertEquals(true, file.exists());
How can this be done?
This is the method under test (cut down)
#Override
public void load(InputArchive archive, int idx)
{
archive.beginNode("Files", idx);
File file = new File(archive.load("Path"));
if(file.exists())
{
//if it gets here it'll pass the test
}
}
I think that the above will solve my problem, but in case there's a better/alternative way to solve my problem I'll tell you why I'm trying to do this:
The reason I want to do this is that I'm reading an XML which will create a file based off a tag, it will then test this fileObjectCreatedFromXML to see if it exists and if it does then it will do some other stuff which I need it to do.

Is possible to mock your File object even if is created inside your class and you do not have any way to inject it or reference it.
I had this problem few weeks ago and PowerMock can help you here.
You have to annotate your test class to run with PowerMockRunner. See the following example:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClassThatWillBeTested.class)
public class MyUnitTest{
private File mockedFile = mock(File.class);
#Before
public void setUp() throws Exception {
PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(mockedFile);
}
}
#Test
public void myTestMethod(){
//test your method here...
}
If you create only one file object this should work well for you.
Also now you can manipulate your mock object to return what you want.
when(mockedFile.exists()).thenReturn(true);

Related

How to mock the BooleanUtils class or an application property?

I'm trying to create a when sentence, but I can't do it well because I don't know how to mock correctly whatever.
I have this code:
public class OperationMovement {
#Value("${operation.check}")
private Boolean needToCheck;
private void checkOperation() {
// Code
if (BooleanUtils.isTrue(needToCheck)) {
// More code
}
}
}
I need to create a test with Mockito, but I don't know how to mock this if else.
I have tried to mock the BooleanUtils this way:
#Mock
BeanUtils beanUtils;
// Code and more testing code
when(booleanUtils.isTrue(anyBoolean())).thenReturn(true);
But this returs an error.
I have tried the following too, but I have the same error:
when(BooleanUtils.isTrue(anyBoolean())).thenReturn(true);
I need to mock that propertie or the BooleanUtils class, but I don't know how.
Quick example usage:
private OperationMovement classUnderTest;
...
#Test
void testOperationIsTrue() {
// For this test case, you are setting it to true
ReflectionTestUtils.setField(classUnderTest,"needToCheck",true);
}

Easymock.expect throws IllegalStateException

I see that in this piece of code,
expect(myService.getAll(anyBoolean())).andReturn(objectList).anyTimes();
replay(scopeService);
That expect statement statement is throwing
IllegalStateException - missing behavior definition for the preceding method call:
myService.getAll(true)
Usage is: expect(a.foo()).andXXX()
I understand that if it throws this exception if I dont have the andReturn, or if I missed calling the replay, or if my object is not a mock. I have checked all of that and it is not the case! Can someone please let me know if something else could be wrong?
I have around a 50 expect/replays before and nothing has an issue.
You haven't provided more code so I assume that your code looks like this more or less:
import static org.easymock.EasyMock.*;
public class SomeTests {
static class Foo {
public List<Integer> getAll(boolean value) {
throw new RuntimeException();
}
}
public void someTestCase() {
Foo mock = createMock(Foo.class);
List<Integer> ret = Collections.singletonList(1);
expect(mock.getAll(anyBoolean())).andStubReturn(ret);
replay(mock);
mock.getAll(true); // returns a list with single element 1 rather than throwing an exception
}
}
my advice is that:
Check if myService instance is created by one of mocking methods
Reply should be called on myService as it switches mode of a mock
I figured out the issue. The issue was that the mock myService was being used to create the object that was being tested(since it has it as a member) and to create another mock object needed for the tests.
When I changed them to use two different myService(myService, myService1) it worked! I am not sure how that would help, but it did!

How test an method exception when the file exists and cannot be deleted?

I would like to test the exception trowed by this piece of code:
private void delete(final File file, final String fileName) {
boolean deleted = file.delete();
if (deleted) {
log.info("File {} was deleted", fileName);
} else {
throw new RuntimeException("The file exists but could not be deleted");
}
}
My first idea was create a temporary file that can't be deleted in my unit test. For sure, I would like to control this behavior to delete this file after the test. But I supposed that this is not possible, it's contradictory. Set the file to "read only" not works for this case.
So, any ideas?
I could create a new class and pass the responsibility to delete the file and return the boolean, so I could mock it and test my exception. But I would like to explore another possibilities using Junit and Java before do this.
I think that creating a temporary file or locking a file is overkill and not required.
The fact that a file cannot be deleted depends on runtime conditions on the filesystem where this file is hosted. You don't need to reproduce these conditions in your unit test and besides reproducing these conditions in the unit test will not guarantee you that the file used at runtime will be not deletable. So I think that this point should not be considered in the unit test.
You could simply mock/stub File.delete() to make it return false and assert that a RuntimeException is thrown : the actual behavior to assert.
With Mockito for example :
#RunWith(MockitoJUnitRunner.class)
public class FileServiceTest {
#Test(expected = RuntimeException.class)
public void myMethodToTest() throws Exception {
File file = Mockito.mock(File.class);
Mockito.when(file.delete()).thenReturn(false);
FileService.delete(file, "test");
}
}
In general I would do the following:
#RunWith(MockitoJUnitRunner.class)
public class FileServiceTest {
#Mock
private File file;
#Test
public void myMethodToTest() {
doReturn(false).when(file).delete();
try{
FileService.delete(file, "test");
fail("this test should throws an exception.")
} catch (RuntimeException e) {
assertEquals("The file exists but could not be deleted", e.getMessage());
}
}
}
On this example the test fails in case it doesn't throw any exception and, in case it gets a RuntimeException, it verify if that exception is the one you throw.
Use mock objects when writing unit tests.
Get Mockito and create a mock of the file input parameter.
Then set the return value of the delete method on your mock to return true or false based on the desired test outcome.
Use a different file and test deletion on that file. The extension could be the same for the second file, but the content and location may not need to be.

Can I ignore aspect of a method while mocking it using Mockito?

I have a class with a few methods advised through an input validation aspect (validates whether all input parameters are not-null/non-empty strings).
I am facing an issue while writing test case for them and want to verify if this is indeed a bad design issue.
Here's a very simplified version of my class:
public class A {
public String one(String word) {
// Some actions
String val = two(word2);
// Some more actions
}
protected String two(String word) {
// Some actions
}
}
Now while writing test cases for one() I use Mockito and want to mock calls to two(). So I use:
#Spy
A a;
#Test
void test() {
doReturn("Bye").when(A).two(Mockito.anyString());
a.one("hello");
// Some validations
}
This test fails as the: doReturn() line fails with input being empty for two().
Should I not mock two() or can I make this work somehow?
Edit:
Adding a more specific example related to the two methods being present in two different classes as requested:
Create a page through a WebService. This builds a putRequest, executes it and returns a response.
public class AUtility implements BaseUtility {
public Response create(Params params) {
try {
PutMethod putRequest = buildPUTRequest(params.getAttr1(), params.getAttr2());
return Utils.buildResponse(client.executeMethod(putRequest),
params.getAttr3(),
params.getAttr4());
} catch (Exception e) {
throw new AppException(e);
}
}
}
The put request marshals the data into a file to write it through the HttpClient
private PutMethod buildPUTRequest(final String url, final Object obj) throws IOException, JAXBException {
// Create a temp file to store the stream
File tempFile = File.createTempFile(APPLICATION_LABEL, XML_LABEL);
decoder.marshal(obj, tempFile);
// Build the put method
return putMethod;
}
XMLMarshaller
public interface XMLDecoder implement Decoder {
public void marshal(Object obj, File tempFile) throws IOException, JAXBException {
// Perform marshalling operations
}
}
The test fails on line2 with the inputs being null.
#Test
public void createPageParamsHttpException() throws HttpException, IOException, JAXBException {
expectedException.expect(AppException.class);
doNothing().when(decoder).marshal(Mockito.anyString(), Mockito.any(File.class));
doThrow(HttpException.class).when(client).executeMethod(Mockito.any(HttpMethod.class));
Params params = new Params(new Application(),
APPLICATION_URL_LABEL,
SITE_NAME_LABEL,
URL_WITHOUT_HTTP_N_HTML);
utility.createPage(params);
}
Any idea how should I proceed for the same?
You don't want to do this.
You are inherently changing the behavior of the class. If you change what two() does, how do you know that one() will do what it's supposed to do in production?
If you truly want to do this, you should extract the behavior of two() into another top level class, and then inject the dependency into A. Then you can mock this dependency and you don't have to worry about going to the trouble of creating a partial mock for A.
In a similar vein, if you must keep two in the same class (because it's behavior is part of the same responsibility that is assigned to A - see the Single Responsibility Principle - why is it public?
The reason you are having trouble is because you are violating the SRP, see my note above. You said this:
This builds a putRequest, executes it and returns a response.
You should not be trying to test the behavior of all three of those things at the same time. Ultimately, this method does not really do anything. The buildPUTRequest method does, and shouldn't be in a class called AUtility, it should be in a class RequestFactory. Then, you would want to test the Utils.buildResponse method, except that shouldn't be in a class called Utils, it should be in a class called Responder or something... and this method ABSOLUTELY should not be static.
Work on naming your classes better things, and if you can't come up with a good name, that means the class probably does too much and should be refactored. And a method that wraps the work in two other methods doesn't need to be unit tested. Integration tested, perhaps, but that's another story.

Mock a private static field with JMockit?

I have a class like the following;
class ClassA {
private static File myDir;
// myDir is created at some stage
private static String findFile(final String fileName) {
for (final String actualBackupFileName : myDir.list()) {
if (actualBackupFileName.startsWith(removeExtensionFrom(backupFile))) {
return actualBackupFileName;
}
}
}
}
So, basically, I want to test this class by mocking out the File class so that when list() is called on it it returns a list of strings I define in my test class.
I've got the following but its not working at the minute, there's probably something obvious I'm doing wrong - I'm new to JMockit - any help is much appreciated!
#Mocked("list") File myDir;
#Test
public void testClassA() {
final String[] files = {"file1-bla.txt"};
new NonStrictExpectations() {{
new File(anyString).list();
returns(files);
}};
String returnedFileName = Deencapsulation.invoke(ClassA.class, "findFile","file1.txt");
// assert returnedFileName is equal to "file1-bla.txt"
}
When running the above test I get a NullPointerException for the myDir field in ClassA - so it looks like its not getting mocked properly?
You can use the setField method from the Deencapsulation class. Note example below:
Deencapsulation.setField(ClassA, "File", your_desired_value);
JMockit (or any other mocking tool) does not mock fields or variables, it mocks types (classes, interfaces, etc.) Where the instances of those types get stored inside the code under test is not relevant.
Example test for ClassA:
#Test
public void testClassA(#Mocked File myDir)
{
new Expectations() {{ myDir.list(); result = "file1-bla.txt"; }};
String returnedFileName = new ClassA().publicMethodThatCallsFindFile("file1.txt");
assertEquals("file1-bla.txt", returnedFileName);
}
The above should work. Note that testing private methods directly (or accessing private fields) is considered bad practice, so I avoided it here. Also, it's best to avoid mocking the File class. Instead, test only your public methods, and use actual files instead of mocking the filesystem.
try out this:
new Expectations {{
invoke(File.class, "list", null, null);
returns(files);
}}

Categories