I am trying to Unit Test a method for which I need to create the object of the class using a constructor.This is how the constructor looks like :
public WebformsClinEventBusiness(Webform webForm, String dataEntryModel, String obsBatId) {
this.webformObj = webForm;
this.eventObj = webForm.getEvent(obsBatId);
this.progressNoteText = webForm.getProgressNoteNext();
this.formValues = webForm.getFormValues();
this.lastFormValues = webForm.getLastFormValues();
this.emptyFormValues = webForm.getEmptyFormValues();
this.formVersion = webForm.getFormVersion();
this.dataEntryModel = dataEntryModel;
this.headerValues = webForm.getHeaderValues();
this.OBS_BAT_ID = obsBatId;
this.userPreferences = (CompSoapUserPreferences)webForm.getRequest().getSession(false).getAttribute(userPreferences.getSESName());
}
The problem is in the last line. I have a mock webform object and have set the expectations like this:
one (mockWebForm).getRequest();
will(returnValue(mockRequest));
one (mockRequest).getSession(false);
will(returnValue(mockSession));
allowing (mockSession).getAttribute(_SES_NAME);
will(returnValue(mockCompSoapUserPreferences));
allowing (mockCompSoapUserPreferences).getSESName();
will(returnValue(_SES_NAME));
When the code hits webform.getRequest() instead of calling the mock it calls the actual method which returns null and I end up with a null pointer exception.
Any ideas ? I would really appreciate any input on this.
Thanks for your time !
Related
I just have an Object that I mock with Mockito, and I need to do the equivalent with Spock.
How do you guys recommend to do it?
This is the way that I did with Mockito
XptoOutputBoundary xpto;
doAnswer({ invocation ->
xpto = invocation.getArgumentAt(1, OutputBoundary.class)
xpto.response.response.abcd01 = abcd01
xpto.response.response.abcd02 = abcd02
xpto.response.response.abcd03 = abcd03
xpto.response.response.abcd04 = null
xpto.response.response.abcd05 = null
xpto.response.response.abcd06 = abcd06
xpto.response.response.abcd07 = abcd07
return null
}).when(service).execute(any(), any())
How can I mock in the same way, but using Spock?
UPDATE
Hello!
I've tried one of the suggestions, but it still not work... the "xpto" object keeps getting null using spock
Here is how is the code now:
given: 'i have a valid object'
AbcdObjectXptoResponse xptoResponse = Fixture.from(AbcdObjectXptoResponse.class).gimme("valid")
AbcdObjectRequest request = Fixture.from(AbcdObjectRequest.class).gimme("valid")
XptoOutputBoundary xpto;
repository.execute(_ as XptoOutputBoundary, _) >> { args ->
xpto = args[0]
xpto.response.response.abcd01 = abcd01
xpto.response.response.abcd02 = abcd02
xpto.response.response.abcd03 = abcd03
xpto.response.response.abcd04 = null
xpto.response.response.abcd05 = null
xpto.response.response.abcd06 = abcd06
xpto.response.response.abcd07 = abcd07
}
when: 'the request is performed'
def response = service.getAbcdObjectRequest(request)
Your example code appears to be very Java-flavored Groovy using Mockito, returning null for some particular reason (instead of simply being void). Operating on that assumption, then the Spock equivalent would be something like this:
MyService service = Mock()
def 'test case'() {
when:
'things happen'
then:
// you really should put constraints on your arguments, not just any() or _
service.execute(_ as XptoOutputBoundary, _) >> { args ->
XptoOutputBoundary xpto = args[0] // or 1?
// do the same things
}
}
I wrote the dynamoDB code which stores list of items.
mapper.batchSave(trafficSensorReadings)
This will return.
List<FailedBatch>
I want to mock the mapper.batchSave and then return one failed job. How can I achieve it? I am using mockito and Junit.
I wrote something like this. But not useful.
when(dynamoDBMapper.batchSave(eq(List.class))).thenReturn(mock(List.class));
A complete example follows
#Test
public void test() {
FailedBatch failedBatch = mock(FailedBatch.class);
List<FailedBatch> failedBatchList = new ArrayList<>();
failedBatchList.add(failedBatch);
DynamoDBMapper dynamoDBMapperMock = mock(DynamoDBMapper.class);
when(dynamoDBMapperMock.batchSave(any(List.class))).thenReturn(failedBatchList);
tested.testedMethodCall();
verify(dynamoDBMapperMock).batchSave(any(List.class));
}
First, I think you might want to use Mockito.any() instead of Mockito.eq().
Second, I don't see why you would want to mock the list. You can just create one and return it
// GIVEN
FailedBatch batch1 = /**/;
FailedBatch batch2 = /**/;
List<FailedBatch> failedBatchList = Lists.newArrayList(batch1, batch2);
// WHEN
when(dynamoDBMapper.batchSave(any(List.class))).thenReturn(failedBatchList);
Object someResult = yourFunctionTestCall();
// THEN
verify(someResult)...
I'm putting more attention into unit tests these days and I got in a situation for which I'm not sure how to make a good test.
I have a function which creates and returns an object of class X. This X class is part of the framework, so I'm not very familiar with it's implementation and I don't have freedom as in the case of my "regular collaborator classes" (the ones which I have written). Also, when I pass some arguments I cannot check if object X is set to right parameters and I'm not able to pass mock in some cases.
My question is - how to check if this object was properly created, that is, to check which parameters were passed to its constructor? And how to avoid problem when constructor throws an exception when I pass a mock?
Maybe I'm not clear enough, here is a snippet:
public class InputSplitCreator {
Table table;
Scan scan;
RegionLocator regionLocator;
public InputSplitCreator(Table table, Scan scan, RegionLocator regionLocator) {
this.table = table;
this.scan = scan;
this.regionLocator = regionLocator;
}
public InputSplit getInputSplit(String scanStart, String scanStop, Pair<byte[][], byte[][]> startEndKeys, int i) {
String start = Bytes.toString(startEndKeys.getFirst()[i]);
String end = Bytes.toString(startEndKeys.getSecond()[i]);
String startSalt;
if (start.length() == 0)
startSalt = "0";
else
startSalt = start.substring(0, 1);
byte[] startRowKey = Bytes.toBytes(startSalt + "-" + scanStart);
byte[] endRowKey = Bytes.toBytes(startSalt + "-" + scanStop);
TableSplit tableSplit;
try {
HRegionLocation regionLocation = regionLocator.getRegionLocation(startEndKeys.getFirst()[i]);
String hostnamePort = regionLocation.getHostnamePort();
tableSplit = new TableSplit(table.getName(), scan, startRowKey, endRowKey, hostnamePort);
} catch (IOException ex) {
throw new HBaseRetrievalException("Problem while trying to find region location for region " + i, ex);
}
return tableSplit;
}
}
So, this creates an InputSplit. I would like to know whether this split is created with correct parameters. How to do that?
If the class is part of a framework, then you shouldn't test it directly, as the framework has tested it for you. If you still want to test the behaviour of this object, look at the cause-reaction this object would cause. More specifically: mock the object, have it do stuff and check if the affected objects (which you can control) carry out the expected behaviour or are in the correct state.
For more details you should probably update your answer with the framework you're using and the class of said framework you wish to test
This is possibly one of those cases where you shouldn't be testing it directly. This object is supposedly USED for something, yes? If it's not created correctly, some part of your code will break, no?
At some point or another, your application depends on this created object to behave in a certain way, so you can test it implicitly by testing that these procedures that depend on it are working correctly.
This can save you from coupling more abstract use cases from the internal workings and types of the framework.
Hi I have plenty of methods which returns string which I need to unit tests. Now challenge for me is is how do I do code coverage? For e.g. My method looks like the following
Public String getSqlToDoXYZ(Myconfig config) {
StringBuilder sb = new StringBuilder() ;
sb.append( "SELECT BLAH BLAH");
sb.append("WHERE ABC="+config.getABC());
return sb.toString() ;
}
Please give your ideas how to unit tests such scenario? I am using mockito to do unit testing. I am new to both mockito and unit testing please guide. Thanks in advance.
As pointed elsewhere, using Strings for SQL statements is dangerous, regarding SQL injections.
That being said, you simply have to call the method, and compare the result to a String you build "by hand" :
public void testBuildSqlToDoXYZ() throws Exception {
WhateverYourObjectIs yourObject = new WhateverYourObjectIs();
MyConfig myConfig = new MyConfig();
myConfig.setABC("foo");
String sql = yourObject.getSqlToDoXYZ(myConfig);
assertEquals("SELECT BLAH BLAH WHERE ABC='foo'", sql);
}
Mockito would only be helpfull in this case if is impossible for you to create a "MyConfig" object by hand.
There might be something else in your code that makes that difficult, but you haven't really provided us enough info.
I can't see any difficulties to test a method that returns a string.
public void testSqlToDoXYZ()
{
MyObj testTarget = new MyObj(/*Parameters if needed*/);
Config config = new Config();
/*Config config = new ConfigMock();*/
String expectedResult = "SELECT BLAH BLACH WHERE ABC=123;";
assertEquals(epxectedResult, testTarget.getSqlToDoXYZ(config));
}
The key is, that you have to know your result. If the config.getABC() call could return different values, you have to make sure it always provides the same values for your test. So you might have to mock your config object or put fake data into your config provider.
Well, I am right now testing legacy code. And, I am somewhere near to pass this test, but its stuck at the line having comments on it. Here is the snippet
new NonStrictExpectations(){
SASCustomerDataAssemblerBD assembleBd;
CustomerTOs tos;
CustomerSASTO to;
Another rowTo;
SelectionJobLogBD logBd;
{
SASCustomerDataAssemblerBD.getInstanceUsingEjbRef(); result = assembleBd;
assembleBd.getData(); result = tos;
..
..
//This line is not being invoked.
//Instead the actual line of code is working. Which is,
//Collections.max(someCollection, someComparator);
//Hence I am stuck because getting null in "to"
invoke(Collections.class, "max", new ArrayList(), new MaxDateComparator()); result = to;
to.getSasDataRow(); result = rowTo;
SelectionJobLogBD.getInstanceUsingEjbRef(); result = logBd;
..
}
};
new TaskSASCustomerReading().execute();
Whereas, all the values of result are mocked up.
Solved it, in another way :). Mocked the original method -- only the method that calls Collections.max() under the hood.
new MockUp<TaskSASCustomerReading>()
{
#Mock
// This original method is invoking Collections.max().
// Therefore, I just mocked this one, other methods are all original
String findLatestSelectionDate(Collection customerTOs) {
return "";
}
};
new Expectations(){
SASCustomerDataAssemblerBD assembleBd;
CustomerTOs tos;
SelectionJobLogBD logBd;
{
try {
SASCustomerDataAssemblerBD.getInstanceUsingEjbRef(); result = assembleBd;
assembleBd.getData(); result = tos;
SelectionJobLogBD.getInstanceUsingEjbRef(); result = logBd;
}catch(Exception e){}
}
};
new TaskSASCustomerReading().execute();
None the less, I was totally misunderstood the thing in the first place, when I asked the question. In my original question, I am in fact trying to invoke a method, instead of replacing it. (P.S. Never work after hours. ;))