I'm currently having a problem with a Unit test using EasyMock.
Expectation failure on verify:
FileConverter.convert(file, file2): expected: 1, actual: 1
This is the only failure in the class and it fails on the verify method below. I have tried to Google the message, but this only brings up results for "expected: 1, actual: 1 (+1)", and the +1 implies the error is different.
I have tried to simplify the structure of the failing EasyMock test for demonstration. Please forgive any typos:
#Test
public void testScan() {
String[] testFiles = { "file", "file2" };
FileConverter converterMock = EasyMock.createMock(FileConverter.class);
Poller poller = new Poller(new File("testFolder"), converterMock);
for (String testFile : testFiles) {
converterMock.convert(new File(testFile));
EasyMock.expectLastCall().once();
}
EasyMock.replay(converterMock);
for (String testFile : testFiles) {
poller.scan();
}
EasyMock.verify(converterMock);
}
I don't think the code itself is particularly relevant but I have included it for completeness - what I am really looking for is an explanation of what "expected 1, actual 1" could mean in the context of the EasyMock.verify method.
Thanks in advance!
Another optional case is when using a multithreaded environment, it might occur that the desired method has invoked on the mock object after the test has already ended.
Error messages can be very unclear from these test runs. I do see it fails on expecting a convert method call signature with 2 File arguments. So try expecting that by completing/replacing the following line in your test:
converterMock.convert(new File(testFile));
with something like:
File file1 = new File(testFile1);
File file2 = new File(testFile2);
converterMock.convert(testFile1, testFile2);
Also experiment with less specific matching like:
converterMock.convert(EasyMock.isA(File.class), EasyMock.isA(File.class));
or
File file1 = new File(testFile1);
File file2 = new File(testFile2);
converterMock.convert(EasyMock.eq(file1), EasyMock.eq(file2));
Are you using a recent version of EasyMock? Because I do remember old version performing strange calculation sometimes.
I tried your code and if I guessed correctly the content of the scan method.
void scan(String file) {
converter.convert(new File(file));
}
It should work perfectly.
Related
I've already read similar questions on SO like this, but I can't solve my problem.
I've modified an existing class and when I try to build it with ant I get the following unit test failed error:
java.lang.IllegalStateException: missing behavior definition for the preceding method call getLast(class mypackage.model.MyObj, 1)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:43)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:92)
at mypackage.service.MyService$$EnhancerByCGLIB$$347f5838.getLast()
at mypackage.controller.MyController.myControllerMethod(MyController.java:265)
at mypackage.controller.MyController.myControllerMethodTest(MyControllerTest.java:207)
In MyController.java I've added a piece of code like (the error is at line 265):
263. public void myControllerMethod(Integer id) {
264. String myString = null;
265. MyObj myObj = (MyObj) myService.getLast(MyObj.class, id);
266. try {
267. myString = myObj.getMyProp().getMyObj();
268. } catch (Exception e) {
269. myString = "";
270. }
MyControllerTest.java simply calls myControllerMethod, like:
207. myController.myControllerMethod(1);
I've already tried to add an "expectation" before the line 207, like:
206. EasyMock.expect(myServiceMock.getLast(MyObj.class, 1));
rather than:
206. EasyMock.expect(myServiceMock.getLast(MyObj.class, 1)).andReturn(new MyObj());
But to no avail.
Can anyone help me, please?
Ok, I solved with EasyMock.replay(myServiceMock) as I found in this example.
That's a kind of "activation" of the expectation inserted before.
I have some pretty simple code as shown below.
#Test
public void bugInInvokingASpyAndVerification() throws ColdDayException {
//given
Engine en = new Engine();
Engine spyEngine = spy(en);
Vehicle realDeal = new Vehicle(new Wheel(), spyEngine, new Brake());
Vehicle spyVehicle = spy(realDeal);
//When part - set-up stubs
when(spyVehicle.start(true)).thenReturn("Sure");
//Mockito.reset(spyVehicle);
//then part - actual calls + verifications
String x = spyVehicle.start(true);
assertEquals(x, "Sure");
verify(spyVehicle, times(1)).start(true);
verify(spyEngine, atLeastOnce()).startEngine(true);
verify(spyEngine, times(1)).startEngine(true);
}
The above code seems to record the 'when' call as the first call to the 'start' & hence the first 'verify' fails. The code works only when I uncomment the call to 'reset'. I am using Mockito 2.1.0 on Windows, with Java 1.8.
Indeed, in the line when(spyVehicle.start(true)).thenReturn("Sure"); you call start.
There are several ways to avoid this.
One of them is use doReturn:
doReturn("Sure").when(spyVehicle).start(eq(true));
Notice, that here we are are doing stubbing and not calling the method.
I am very new to Sonar.
I am trying to make my own plugin for sonar. After downloading plugin example, I make it eclipse ready using mvn eclipse:eclipse and import to workspace. It is compiling fine.
But I need to add my own Rule files to it.
For that purpose, I have created 2 files.
MyCustomNLSRuleTest .java
package org.sonar.samples.java.checks;
import org.junit.Test;
import org.sonar.java.checks.verifier.JavaCheckVerifier;
public class MyCustomNLSRuleTest {
#Test
public void check() {
// Verifies that the check will raise the adequate issues with the expected message.
// In the test file, lines which should raise an issue have been commented out
// by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}"
JavaCheckVerifier.verify("src/test/files/MissingCheck.java", new MyCustomSubscriptionRule());
}
}
The actual rule is provided to me in the following java file which looks like below -
MissingCheck.java
public class MissingCheck extends Check
{
private HashMap<Integer, Integer> lineStringMap;
#Override
public void beginTree(DetailAST aRootAST) {
super.beginTree(aRootAST);
lineStringMap = new HashMap<>();
}
#Override
public int[] getDefaultTokens() {
return new int[] { TokenTypes.STRING_LITERAL};
}
#Override
public void visitToken(DetailAST ast) {
DetailAST parent = ast.getParent();
if (parent != null) {
DetailAST grandpa = parent.getParent();
if (isAnnotation(grandpa.getType())) {
return;
}
}
Integer count = lineStringMap.get(ast.getLineNo());
if (count == null) {
count = new Integer(1);
} else {
count++;
}
FileContents contents = getFileContents();
String[] line = contents.getLines();
if (line.length >= ast.getLineNo()) {
String l = line[ast.getLineNo() - 1];
if (!l.contains("$NON-NLS-" + count + "$")) {
log(ast.getLineNo(), "String_Not_Externalized", new Object[] { ast.getText() });
}
}
lineStringMap.put(ast.getLineNo(), count);
}
/**
* Checks if type is an annotation.
* #param type to check
* #return <code>true</code> if type is an annotation.
*/
private boolean isAnnotation(int type) {
return (type >= TokenTypes.ANNOTATION_DEF && type <= TokenTypes.ANNOTATION_ARRAY_INIT);
}
}
But, I am trying to do mvn clean package this project, it gives me error:
Results :
Tests in error:
MyCustomNLSRuleTest.check:13 ยป IllegalState At least one issue expected
Tests run: 8, Failures: 0, Errors: 1, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ---------------------------------------------------------------------
Any idea, how I can add a new rule in the plugin?
Thanks!
Okay, it seems that you are very far from what you are supposed to do when writing custom rules for the java plugin... A few questions first:
Did you actually tried to have a look at the dedicated page from the SonarQube confluence? http://docs.sonarqube.org/display/DEV/Custom+Rules+for+Java
Did you actually look at the following links before trying to write a rule?
The rule already implemented in the example project,
How they are tested,
With which test files,
How they are registered in the custom plugin,
The comments from the unit test you are actually writing.
Now... Let's start by explaining to you what you are currently doing, as apparently it's not clear at all.
You created a test file called MyCustomNLSRuleTest.java, which should theoretically correspond to a rule called MyCustomNLSRule. Note that it's probably not the case, as you are saying that the rule is provided to you in the MissingCheck.java file.
Your unit test uses JavaCheckVerifier to verify that the file provided as argument, "src/test/files/MissingCheck.java", will raise all the expected issues when playing the rule MyCustomSubscriptionRule against it.
At this point, you are not testing at all your MissingCheck, but using it as data for the MyCustomSubscriptionRule rule... And it's probably your main issue.
However, if this is actually really what you are trying to achieve, it means that:
You modified the rule MyCustomSubscriptionRule to have a custom behavior, different from the one from the original example project.
When executing it on the file MissingCheck.java, the check is supposed to raise issue (with the line having issue being commented out with // Noncompliant {{expected message}})
Your custom rule does not work, as it apparently raised no issue at all when playing the test.
Please look at all the links provided above to see how custom rules works, what is available in the java plugin API, and what you can achieve with it.
i am using eclemma and trying to increase my test coverage:
so far this is my code:
public RolesResponse findRolesByTenant(RolesRequest rolesRequest)
{
RolesResponse rolesResponse = new RolesResponse();
List<Role> roleList = null;
if (StringUtils.isNotBlank(rolesRequest.getTenantCode()))
{
roleList = roleFunctionService.getAllRolesAndFunctionsByTenant(rolesRequest.getTenantCode());
}
if (CollectionUtils.isNotEmpty(roleList))
{
rolesResponse.setRoles(roleList);
}
else
{
rolesResponse.setError(LayerContextHolder.getErrorObject());
}
return rolesResponse;
}
and here is my test:
#Test
public void findRolesByTenantTest()
{
RolesRequest rolesRequest = new RolesRequest();
rolesRequest.setTenantCode("test");
ErrorObject errorObject = new ErrorObject();
RolesResponse rolesResponse = rolesProcessService.findRolesByTenant(rolesRequest);
Assert.assertNull(rolesResponse.getError());
}
the only line eclemma is highlighting in red is this one:
rolesResponse.setError(LayerContextHolder.getErrorObject());
can someone help me in constructing the final test needed to cover this line
thanks
I'm really not a fan of your test anyway - what are you trying to prove by the error being null? That the list came back with something? Also, are you certain that your service will return the result you want in your test every single time?
Don't think of tests in terms of coverage; this will lead to brittle tests and tests that give a false sense of security. What you want to do is write tests that cover each condition that the code could encounter, and the line coverage can follow from that.
From your code, I see two cases.
roleFunctionService#getAllRolesByFunctionAndTenant can return a non-empty list.
It's implied that the resultant rolesResponse#roles contains whatever was in the list provided by the method, and this should be verified.
It's also implied that there is no error set on the object, so it should be null.
roleFunctionService#getAllRolesByFunctionAndTenant can return an empty list
Either the resultant rolesResponse#roles are empty or null; it'd be better if it were empty.
It's implied that there is an error on the object, which is specifically provided by LayerContextHolder.getErrorObject(). You should check to see that it's exactly that.
You'll get to the whole approach of writing this test through the use of a mocking framework.
I am using a series of Strict Mocks generated with EasyMock 3.2 to test a method that call's itself recursively. By setting the expectations of my mocks I can control the method so that it only calls itself once and then exits. However, I am seeing some very strange behaviour from EasyMock which looks like a bug, where it get's confused about the number of times a method is expected.
For example:
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
expect(srcCollection.getURI()).andReturn(src);
replay(srcCollection, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(srcCollection, broker);
Leads to the error from EasyMock:
java.lang.AssertionError:
Expectation failure on verify:
Collection.getURI(): expected: 2, actual: 1
at org.easymock.internal.MocksControl.verify(MocksControl.java:226)
at org.easymock.EasyMock.verify(EasyMock.java:2080)
I have only instructed EasyMock to expect one result, so why does it think I want two? I also get the same error if I change my expectation to this:
expect(srcCollection.getURI()).andReturn(src).once();
...And it get's stranger...
If I change my expectation to this:
expect(srcCollection.getURI()).andReturn(src).times(2);
I get the error:
java.lang.AssertionError:
Expectation failure on verify:
Collection.getURI(): expected: 3, actual: 1
at org.easymock.internal.MocksControl.verify(MocksControl.java:226)
at org.easymock.EasyMock.verify(EasyMock.java:2080)
And, further if I change my expectation to this:
expect(srcCollection.getURI()).andReturn(src).anyTimes();
I get an even stranger error:
java.lang.IllegalStateException: last method called on mock already has a non-fixed count set.
at org.easymock.internal.MocksControl.replay(MocksControl.java:216)
at org.easymock.EasyMock.replay(EasyMock.java:2012)
Does anyone have any suggestions, or know of any limitations with EasyMock in recursive functions?
In my case I repeated same expected values 2 times. And it throws:
java.lang.IllegalStateException: last method called on mock already has a non-fixed count set.
E.G.
SchedulingDataForVersion dataForVersion = createNiceMock(SchedulingDataForVersion.class);
TaskSource mockedTaskSource = createNiceMock(TaskSource.class);
expect(mockedTaskSource.getOrderElement()).andReturn(orderLine).anyTimes();
expect(mockedTaskSource.getOrderElement()).andReturn(orderLine).anyTimes();
replay(dataForVersion, mockedTaskSource);
Correct one is:
SchedulingDataForVersion dataForVersion = createNiceMock(SchedulingDataForVersion.class);
TaskSource mockedTaskSource = createNiceMock(TaskSource.class);
expect(dataForVersion.getOrderElement()).andReturn(orderLine).anyTimes();
expect(mockedTaskSource.getOrderElement()).andReturn(orderLine).anyTimes();
replay(dataForVersion, mockedTaskSource
The error occurs when you add .anyTimes() and then you write the same call.
expect(mock.get()).andReturn("string").anyTimes(); --> first call with multiple support
expect(mock.get()).andReturn("string"); --> second call not needed
The solution is to write only the first call with multiple support
expect(mock.get()).andReturn("string").anyTimes();
I can't see anything wrong with this code.
Are the two mocked methods on the broker expected not to be called?
I made a test case. Can you make it fail?
public class AppTest {
public static interface Collection {
String getURI();
}
public static class NativeBroker {
public void checkPermissionsForCopy(Collection srcCollection, String dest,
String newName) {
srcCollection.getURI();
}
public Collection getCollection() {
return null;
}
public String getSubject() {
return null;
}
}
String src = "http://src.com";
String dest = "http://dest.com";
String newName = "my name";
#Test
public void testApp() {
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
expect(srcCollection.getURI()).andReturn(src);
replay(srcCollection, broker);
// run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(srcCollection, broker);
}}