jmockit verifications block throwing Missing 1 invocation to methodName - java

Am trying to run one test case which will update the data into DB. This is my source code of test method.
#Tested // This is class-level scope as I have different test methods.
FirstLevelClass firstLevelClass;
#Test
public void testUpdateDB(#Mocked SecondLevelClass secondLevelClass) throws Exception {
// Updated method by passing an argument.
firstLevelClass.updateDatabaseThroughSecondLevelClass(info);
new Verifications() {{
SecondLevelClass.updateDB(creds, data);
times =1;
}};
Here my intention is to verify the expected invocations to mocked methods[which recorded in expectations]. But, verifications block is giving the following exception message. If I remove times=1, then test case is getting success. That is not my desired result.Can anyone please suggest me what could be wrong in my test case.
mockit.internal.MissingInvocation: Missing 1 invocation to:
SecondLevelClass#updateDB(creds, data)
with arguments: creds, data
Caused by: Missing invocations
Updated Question :
There is one argument to updateDatabaseThroughSecondLevelClass(info), from that argument we are forming creds reference in SecondLevelClass.
Credentials creds = info.getCredentials();
But in verifications block[Which is part of FirstLevelClass] we have created locally test object.
Credentials creds = getCredsTestObject();
This is the reason why it complained about Missing invocations. Because both are two different references in two classes. Can anyone please suggest me how to handle this case.
Thanks In Advance.

It is a known issue in the integration between TestNG and JMockit: https://github.com/jmockit/jmockit1/issues/337

Related

Do I always need `when/thenReturn` for mock object's functions

I am writing a test in Scala where I do something like this --
val svc = mock[Service]
Initializer.fun1(svc)
fun1 internally calls a function svc.fun2 which returns Unit.
My test is failing when it tries to execute svc.fun2 with this error -
java.lang.NoSuchMethodError: org.mockito.internal.invocation.ArgumentsProcessor.expandArgs
As svc has already been mocked, I shouldn't have to mock fun2 ,right ?
Unless I want fun2 to return a specific value
Same thing worked for another codebase of mine, but that's using a different library for Mockito
Update :
I also tried adding a when/thenReturn for fun2 but still getting the same error.
I just did this
when(svc.fun2()) thenReturn()
since it's supposed to return UNIT

Testing for the expected exception message with junit 5

I have a project where I have tests where I deliberately cause a problem and then verify the code responds the way I want it. For this I want to be sure the exceptions not only are the right class but they must also carry the right message.
So in one of my existing (junit 4) tests I have something similar to this:
public class MyTests {
#Rule
public final ExpectedException expectedEx = ExpectedException.none();
#Test
public void testLoadingResourcesTheBadWay(){
expectedEx.expect(MyCustomException.class);
expectedEx.expectMessage(allOf(startsWith("Unable to load "), endsWith(" resources.")));
doStuffThatShouldFail();
}
}
I'm currently looking into fully migrating to junit 5 which no longer supports the #Rule and now has the assertThrows that seems to replace this.
What I have not been able to figure out how to write a test that not only checks the exception(class) that is thrown but also the message attached to that exception.
What is the proper way to write such a test in Junit 5?
Since Assertions.assertThrows returns instance of your exception you can invoke getMessage on the returned instance and make assertions on this message :
Executable executable = () -> sut.method(); //prepare Executable with invocation of the method on your system under test
Exception exception = Assertions.assertThrows(MyCustomException.class, executable); // you can even assign it to MyCustomException type variable
assertEquals(exception.getMessage(), "exception message"); //make assertions here
Thanks to #michalk and one of my colleagues this works:
Exception expectedEx = assertThrows(MyCustomException.class, () ->
doStuffThatShouldFail()
);
assertTrue(expectedEx.getMessage().startsWith("Unable to load "));
assertTrue(expectedEx.getMessage().endsWith(" resources."));

Java test with expected = exception fails with assertion error [duplicate]

This question already has answers here:
Why won't this Expect Exception Junit Test Work?
(2 answers)
Closed 6 years ago.
I'm having an issue with a test case.
The method being tested has a try / catch that catches a MalformedURLException but during testing I get a failure due to a Junit AssertionError that expects a MalformedURLException. But I can't find out what it is actually throwing! Here is my code (created as a MWE in eclipse).
My method that I want to test
public void throwMalFormedURLException(){
String s = new String("www.google.com");
try{
url = new URL(s);
}catch (Exception e){
e.printStackTrace();
e.getClass();
e.getCause();
}
}
the test method
#Test (expected = MalformedURLException.class)
public void testThrowMalFormedURLException() {
MWE testClass = new MWE();
testClass.throwMalFormedURLException();
System.out.println("End of test");
}
This is the output in the console
End of test error details are: java.net.MalformedURLException: no protocol: www.google.com
at java.net.URL.(URL.java:593)
at java.net.URL.(URL.java:490)
at java.net.URL.(URL.java:439)
at MWE.throwMalFormedURLException(MWE.java:12)
at testMWE.testThrowMalFormedURLException(testMWE.java:12)
In the Junit console it says :
java.lang.AssertionError: Expected exception: Java.net.MalformedURLException
But the Junit is reporting failure, even though the console is telling me I've got a MalformedURLException.
What am I doing wrong with this test ?
Thanks for your thoughts.
David
You are catching the exception and therefore it is not being thrown.
If your intent is to test that you are capturing the exception and relaying it back to the 'user' properly, you should create tests for that specifically. You probably don't want UI elements in your unit tests* so this is a place where abstraction and DI have a lot of value. One simple approach is to create a mock object that will listen for the error message and mark a flag when the message is received. Your unit test trigger the error and then pass if the flag is set. You should also have a negative test or assert that the flag is not set prior to throwing the exception.
*Testing the UI is also a good idea but it can be a little slow. There are various tools for automating that. It generally falls in to a different phase of testing. You really want the unit tests to be really fast so that you can run them very frequently.
You have written production code that simply isn't testable. And more specifically: this code doesn't have any "programmatically" observable side effects in the first place.
Meaning: when you write "production code", the code within a method can do three things that could be observed:
Make method calls on objects that are fields of the class under test
Return some value
Throw an exception
For each of these options, you might be able to write testing code:
Using dependency injection, you can put a mocked object into your class under test. And then you can check that the expected methods are invoked on your mock object; with the parameter that you would expect.
You compare the result you get from calling that method with some expected value
You use expected to ensure that a specific exception was thrown
When you look at your code; you can see: it does none of that. It only operates on objects that are created within the method. It doesn't return any value. And, most importantly: it doesn't throw an exception!
Long story short: a caught exception isn't "leaving" the method. It is caught there, and the method ends normally. The fact that you print details about the caught exception doesn't change that.
So, the first thing you have to do: remove the whole try/catch from your production code!
And, if you want to have a more specific test, you can do something like:
#Test
public void testException() {
try {
new MWE().throwMalFormedURLException();
fail("should have thrown!");
} catch ( MalFormedURLException me ) {
assertThat(me.getMessage(), containsString("whatever"));
}
The above:
fails when no exception is thrown
fails when any other exception than MalFormedURLException is thrown
allows you to check further properties of the thrown exception
This is a valid test failure. The test asserts that calling throwMalFormedURLException() will throw MalformedURLException, but since you're catching the exception, it doesn't throw it, so the test fails.

Junit using groovy expected exception

I have Spring boot application. I use Junit+Mockito to unit test it. All the test cases were written using Java. I recently made a decision to write test cases using Groovy though the application code will remain in Java.
I encountered a weird scenario while testing expected exceptions.
Scenario 1: Testing Expected exception using Junit + Groovy (without shouldFail):
#Test(expected = NoResultException.class)
void testFetchAllNoResultsReturned() throws Exception {
List<Name> namesLocal = null;
when(Service.fetchAllNames(id)).thenThrow(
new NoResultException(""))
namesLocal = (service.fetchAllNames(id)
assert(namesLocal==null)
verify(service, times(1)).fetchAllNames(id)
}
As per the above test case, service.fetchAllNames call should throw a NoResultException. This aspect of testing seems to work well. However, the assert and verify after that are not called. As soon as the exception is encountered, the method execution stops. However, my earlier test case written in Java worked perfectly well. This issue happened only after I switched to Groovy.
After doing some Google search I found there is a method called shouldFail provided by GroovyTestCase class which can be used for this scenario as per this link. And it did resolve my issue.
Scenario 2: Testing Expected exception using Junit + Groovy (with shouldFail ):
#Test
void testFetchAllNoResultsReturned() throws Exception {
List<Name> namesLocal = null;
when(Service.fetchAllNames(id)).thenThrow(
new NoResultException(""))
shouldFail(NoResultException.class) {
namesLocal = (Service.fetchAllNames(id)
}
assert(namesLocal==null)
verify(Service, times(1)).fetchAllNames(id)
}
My doubt is, is this how it is supposed to work or am I missing something. If this is how it is supposed to work, is there any reason behind Groovy doing it this way? I tried to look for reasons on the internet but I couldn't get many leads.
However, the assert and verify after that are not called. As soon as the exception is encountered, the method execution stops. However, my earlier test case written in Java worked perfectly well.
Given this code in java:
#Test(expected = NoResultException.class)
void testFetchAllNoResultsReturned() throws Exception {
List<Name> namesLocal = null;
when(Service.fetchAllNames(id)).thenThrow(
new NoResultException(""))
namesLocal = (service.fetchAllNames(id)
....
}
Irrespective of what you have after service.fetchAllNames(id), the call will throw an Exception and the test case ends there. Since you have an expected exception defined, the test case will pass. So the assert and verify after this line of code are never executed in java.
I am not familiar with groovy but from the documentation it looks like your second example using shouldFail is the correct way to test for exceptions in groovy. The shouldFail does not terminate the program - so its similar to putting your method call in a try catch in java

EasyMock JUnit testing throws error on the setter method

I am using easyMock for JUnit testing. I want to test a method which gets a Project object as its arguments and sets the modify date of that project and persists it in db.
So e.g.
public void setProject(Project project) {
project.setModifyDate(new Date());
this.reporsitory.persist(project);
}
Now at my test method I have tow mocked projects. For one of them I have set the return value of the getModifyDate. For the other mocked project object I just call the setProject(mockedProject); Now I assertEqual these two project objects.
The problem is easymock throws me an error at the project.setModifyDate(new Date()) of the class which I am testing.
Exception : Unexpected method call project.setModifyDate(..).. Expected:1, Actual:0.
It seems that it does not expect the setter method. Could you please let me know what I am doing wrong.
Thanks.
Yes, it is because of the type of mock object you created. It expects your code to call every method you defined when the one call executes. I cannot remember the exact name but i think it is something like nicemock, versus a strictmock whick makes your code execute every expected method. You should use EasyMock.createNiceMock() for your mock object. The error you have is because it expects you to call setModifyDate but your code didn't for that call.
Your call is unexpected because you must have not put EasyMock.expected for that method. You need to add your mock object .expected(getMethod).andReturns(something).

Categories

Resources