I'm trying to write unit test for a case when an exception is thrown but somehow it is throwing null instead of exception.
The service call that I'm trying to mock.
private List<Vertex> getVertexList(final String vertexId, GraphTraversalSource graphTraversalSource, final int indexToLoop) {
return graphTraversalSource.V(vertexId).repeat(in().dedup().simplePath()).until(loops().is(indexToLoop)).toList();
}
I wrote the following to mock to throw Exception
#Mock(answer = RETURNS_DEEP_STUBS)
private GraphTraversalSource gts;
Mockito.when(gts.V(anyString()).repeat(any()).until((Predicate<Traverser<Vertex>>) any()).toList()).thenThrow(Exception.class);
Is there any way to mock this so that it throws exception? Thanks in advance.
Assuming your gts and a call to MockitoAnnotations.initMocks(this) in the #Before of the test, this style worked for me:
GraphTraversal v = mock(GraphTraversal.class);
GraphTraversal repeat = mock(GraphTraversal.class);
GraphTraversal until = mock(GraphTraversal.class);
when(gts.V(anyString())).thenReturn(v);
when(v.repeat(any())).thenReturn(repeat);
when(repeat.until((Predicate<Traverser<Vertex>>) any())).thenReturn(until);
when(until.toList()).thenThrow(RuntimeException.class);
gts.V("test-id").repeat(out()).until(__.loops().is(1)).toList();
Depending on what you are doing you might consider avoiding the mock and just throwing an exception in the traversal itself:
GraphTraversalSource g = EmptyGraph.instance().traversal();
g.inject("test-id").sideEffect(x -> {
throw new RuntimeException();
}).toList();
Obviously, that's a little different from what your mock is doing and does require the traversal to actually have data passing through it (hence my use of inject() to start the traversal rather than V() as g is bound to an EmptyGraph in this case.
Related
I have these sealed interface
sealed interface Result<out T> {
data class Success<T>(val data: T) : Result<T>
data class Error(val exception: Throwable? = null) : Result<Nothing>
}
when i tried to assertEquals the Success one, it pass. But when it comes to Error one, it will fail even though the content is identical. Here is simple example:
#Test
fun testSucess() = runTest {
whenever(repository.login("email", "password"))
.thenReturn(someValue)
val expected = Result.Success(data = someValue)
val actual = loginUseCase(LoginRequest("email", "password"))
verify(repository).login("email", "password")
assertEquals(expected, actual) // this will pass
}
#Test
fun testError() = runTest {
val exception = RuntimeException("HTTP Error")
whenever(repository.login("", ""))
.thenThrow(exception)
val expected = Result.Error(exception = exception)
val actual = loginUseCase(LoginRequest("", ""))
verify(repository).login("", "")
assertEquals(expected, actual) // this will fail
assertEquals(expected.toString(), actual.toString()) // this will pass
}
What is causing this and what is possible solution to this? I have read some info that it needs equals() to be overriden, but i still confused as to why it only happens in Error case only and how to properly override the equals method.
Data classes in Kotlin have an implicitly generated equals function automatically derived from all their properties.
The problem you are facing is probably due to the fact that the type of your someValue has a proper equals function, so the equals works for your Success and its property value. But Throwable does not have an equals function which means that two Throwables are only equal if they are the same instance, which is obviously not the case for expected and actual in your test assertion. I can only guess that in loginUseCase, the exception is wrapped inside another exception, or a new exception is created based on the one thrown by the repository?
Kotlin already has a built-in Result type, and I strongly recommend using that one instead of defining your own.
Nonetheless, if you use the built-in type, you will probably face the same problem, since the equals check still fails for the different exception instances.
There are several ways to solve that:
Define your own exception type and override the equals function to return true if they are both of the same type and have the same message.
Check for expected is Error (or with the default Result type that expected.isFailure), and then check that the messages are the same.
Make sure that loginUseCase throws exactly the same exception instance as is thrown by the repository.
Sample code which I tried to mock Appium IOS Driver, It gives Null >Pointer exception
Initializing Driver and AndroidDriver object
Driver driver;
AndroidDriver<AndroidElement> androidDriver;
#SuppressWarnings({ "unchecked" })
#Test
public void getLogAndroid_happyPath() throws Exception{
>Setting logs to mock return type
List<LogEntry> setLogs = new ArrayList<LogEntry>();
setLogs.add(new LogEntry(Level.ALL, 0, "logs"));
driver = new Driver();
Mocking Android Driver with Nice Mock which can result in void
enter code here>return types as well
androidDriver = EasyMock.createNiceMock(AndroidDriver.class);
driver.setAndroidDriver(androidDriver);
EasyMock object call
EasyMock.expect(androidDriver.manage().logs().get(EasyMock.anyString()).getAll()).andReturn(setLogs);
EasyMock.replay(androidDriver);
try {
>Asserting mocked return type
assertTrue(driver.getLog("getLog",5000).contains(setLogs));
} catch (Exception e) {
e.printStackTrace();
}
>Verify EasyMock Object
EasyMock.verify(androidDriver);
EasyMock.reset(androidDriver);
}
You can't do EasyMock.expect(androidDriver.manage().logs().get(EasyMock.anyString()).getAll()).
Even if androidDrive is a mock, it won't cause androidDriver.manage() to return a mock. It will return null. So you probably have a NPE right now.
So you need something like (I'm using a more modern syntax as well):
androidDriver = niceMock(AndroidDriver.class);
what_is_returned_by_manage = mock(WhatIsReturnedByManage.class);
what_is_returned_by_logs = mock(WhatIsReturnedByLogs.class);
what_is_returned_by_get = mock(WhatIsReturnedByGet.class);
expect(androidDriver.manage()).andReturn(what_is_returned_by_manage);
expect(what_is_returned_by_manage.logs()).andReturn(what_is_returned_by_logs);
expect(what_is_returned_by_logs.get(anyString())).andReturn(what_is_returned_by_get);
expect(what_is_returned_by_get.getAll()).andReturn(setLogs);
But actually I would never ever code that. I would add a getAllLogs on what_is_returned_by_manage or something like that.
Does AssertJ (or JUnit) have a way to chain, in a single (fluent) expression, several assertions on the same unit under test where one of the assertions may throw an exception. Essentially, I'm trying to assert that:
If a unit under test (X) doesn't result in a particular exception, which it
may, then assert that a particular property on the unit under test doesn't hold. Otherwise assert the exception is of a certain type.
For example, is there a way to express the assertion that the following erroneous code could EITHER result in an Exception or in a situation where strings.size() != 10000:
#Test/*(expected=ArrayIndexOutOfBoundsException.class)*/
public void raceConditions() throws Exception {
List<String> strings = new ArrayList<>(); //not thread-safe
Stream.iterate("+", s -> s+"+")
.parallel()
.limit(10000)
//.peek(e -> System.out.println(e+" is processed by "+ Thread.currentThread().getName()))
.forEach(e -> strings.add(e));
System.out.println("# of elems: "+strings.size());
}
AssertJ has a concept of soft assertions, are those to be used in the scenarios like that? I'd appreciate some code samples if so.
Or perhaps there are better frameworks specifically design for this type of scenarios?
Thanks.
I'm not sure if that is what you are really looking for but you can try using assumptions.
After executing the code under test, perform an assumption on the result, the following code/assertions will only be executed if the assumptions were correct.
Since 3.9.0 AssertJ provides assumptions out of the box, example:
List<String> strings = new ArrayList<>(); // not thread-safe
int requestedSize = 10_000;
Throwable thrown = catchThrowable(() -> {
Stream.iterate("+", s -> s + "+")
.parallel()
.limit(requestedSize)
.forEach(strings::add);
});
// thrown is null if there was no exception raised
assumeThat(thrown).isNotNull();
// only executed if thrown was not null otherwise the test is skipped.
assertThat(thrown).isInstanceOf(ArrayIndexOutOfBoundsException.class);
You should also have a look at https://github.com/awaitility/awaitility if you are testing asynchronous code.
I came up with the following:
#Test
public void testRaceConditions() {
List<String> strings = new ArrayList<>(); //not thread-safe
int requestedSize = 10_000;
Throwable thrown = catchThrowable(() -> {
Stream.iterate("+", s -> s+"+")
.parallel()
.limit(requestedSize)
//.peek(e -> System.out.println(e+" is processed by "+ Thread.currentThread().getName()))
.forEach(e -> strings.add(e));
});
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(strings.size()).isNotEqualTo(requestedSize);
softly.assertThat(thrown).isInstanceOf(ArrayIndexOutOfBoundsException.class);
});
}
If somebody with more of AssertJ under their belt or some other tools know of a better way, I'd gladly accept their solutions. Thanks!
I'm trying to mock a method that creates a local variable, tries something, and does logging if an exception is thrown. Here's a snippet of code:
public void myFunction() {
//Some stuff
try {
new File("foo").getAbsoluteFile();
} catch (SecurityException e) {
//Do some logging
}
}
I'd like to mock this logging behavior using JMockit (using version 1.8 if it matters). So I created the following test:
#Test(expected=SecurityException.class)
public void testAbsoluteFile(
#Injectable final File file
) throws IOException {
new Expectations(File.class){{
new File(anyString);
result = file;
file.getAbsoluteFile();
result = new SecurityException();
}};
myFunction();
}
The trouble is that this seems to give me a NullPointerException on the inner workings of File.getAbsoluteFile(), which I find absolutely bizarre:
java.lang.Exception: Unexpected exception, expected<java.lang.SecurityException> but was<java.lang.NullPointerException>
Caused by: java.lang.NullPointerException
at java.io.Win32FileSystem.slashify(Win32FileSystem.java:56)
at java.io.Win32FileSystem.resolve(Win32FileSystem.java:330)
at java.io.File.getAbsolutePath(File.java:556)
at java.io.File.getAbsoluteFile(File.java:572)
at com.vue.rescoreservice.ExpectationTest.myFunction(ExpectationTest.java:39)
at com.vue.rescoreservice.ExpectationTest.testAbsoluteFile(ExpectationTest.java:33)
This seems really bizarre as it's saying that a local variable in the Win32FileSystem class (an internal class not in the typical Java API) is throwing a NullPointerException, when it never did before.
The lines that are in the stack trace are as follows:
//In myFunction()
new File("foo").getAbsoluteFile();
and
//In testAbsoluteFile()
myFunction();
Why is this happening? And how can I make it so that JMockit does not throw a NullPointerException on local variables of internal classes?
That issue has been fixed in the latest jMockit version (1.14). If you don't want to migrate now, it's possible to fix the test in 1.8 (see the code below).
In this case, the #Injectable isn't necessary. The constructor of File is mocked for the Expectations and that requires the mocking of the class itself instead of a single instance. In that case, the behavior is equivalent to #Mocked (but File will be partially mocked according to the calls in the Expectations block).
The catch clause in myFunction needs to rethrow the SecurityException to allow the test to pass.
#Test(expected=SecurityException.class)
public void testAbsoluteFile() throws IOException {
new Expectations(File.class) {{
File file = new File(anyString);
file.getAbsoluteFile();
result = new SecurityException();
}};
myFunction();
}
If you prefer to declare the mock as a parameter, it will also work, but File won't be partially mocked (all the methods will be mocked).
#Test(expected=SecurityException.class)
public void testAbsoluteFile(#Mocked final File file) throws IOException {
new Expectations(){{
new File(anyString);
file.getAbsoluteFile();
result = new SecurityException();
}};
myFunction();
}
An update on #Marc-André answer.
In my case with JMockit 1.25 I had to define the file variable outside of the expectations leaving it like:
#Test(expected=SecurityException.class)
public void testAbsoluteFile() throws IOException {
File file = new File("");
new Expectations(File.class) {{
file.getAbsoluteFile();
result = new SecurityException();
}};
myFunction();
}
Maybe it was a change on JMockit prior to the answer.
I've been working on a Java application where I have to use JUnit for testing. I am learning it as I go. So far I find it to be useful, especially when used in conjunction with the Eclipse JUnit plugin.
After playing around a bit, I developed a consistent method for building my unit tests for functions with no return values. I wanted to share it here and ask others to comment. Do you have any suggested improvements or alternative ways to accomplish the same goal?
Common Return Values
First, there's an enumeration which is used to store values representing test outcomes.
public enum UnitTestReturnValues
{
noException,
unexpectedException
// etc...
}
Generalized Test
Let's say a unit test is being written for:
public class SomeClass
{
public void targetFunction (int x, int y)
{
// ...
}
}
The JUnit test class would be created:
import junit.framework.TestCase;
public class TestSomeClass extends TestCase
{
// ...
}
Within this class, I create a function which is used for every call to the target function being tested. It catches all exceptions and returns a message based on the outcome. For example:
public class TestSomeClass extends TestCase
{
private UnitTestReturnValues callTargetFunction (int x, int y)
{
UnitTestReturnValues outcome = UnitTestReturnValues.noException;
SomeClass testObj = new SomeClass ();
try
{
testObj.targetFunction (x, y);
}
catch (Exception e)
{
UnitTestReturnValues.unexpectedException;
}
return outcome;
}
}
JUnit Tests
Functions called by JUnit begin with a lowercase "test" in the function name, and they fail at the first failed assertion. To run multiple tests on the targetFunction above, it would be written as:
public class TestSomeClass extends TestCase
{
public void testTargetFunctionNegatives ()
{
assertEquals (
callTargetFunction (-1, -1),
UnitTestReturnValues.noException);
}
public void testTargetFunctionZeros ()
{
assertEquals (
callTargetFunction (0, 0),
UnitTestReturnValues.noException);
}
// and so on...
}
Please let me know if you have any suggestions or improvements. Keep in mind that I am in the process of learning how to use JUnit, so I'm sure there are existing tools available that might make this process easier. Thanks!
It is true that if you are using JUnit 3, and you are testing whether a particular exception is thrown or not thrown within a method, you will need to use something like the try-catch pattern you define above.
However:
1) I'd argue that there is a lot more to testing a method with a void return value then checking for exceptions: is your method making the correct calls to (presumably mocked) dependencies; does it behave differently when the class is initialized with a different context or different sets of dependencies, etc. By wrapping all calls to that method, you make it hard to change other aspects of your test.
I'm also generally opposed to adding code and adding complexity if it can be avoided; I don't think it's a burden to have to put a try/catch in a given test when it's checking for exceptions.
2) Switch to JUnit 4! It makes it easy to check for expected exceptions:
#Test(expected=IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
If you have the possibility, you should upgrade to JUnit 4.x.
Then your first example can be rewritten to:
#Test(expected=RuntimeException.class)
public void testTargetFunction() {
testObj.targetFunction (x, y);
}
The advantage here is that you can remove you the private UnitTestReturnValues callTargetFunction (int x, int y) method and use JUnit's built in support for expecting exceptions.
You should also test for specific exceptions instead.
Looks like you reimplemented most of JUnit :) In general you don't need to do it. You just call the function you want to call and compare results. If it throws an exception, JUnit will catch if for you and fail the test. If you expect an exception, either you can use the explicit annotation if you are using JUnit 4, or you can use the following pattern:
public void testThrows()
{
try {
obj.DoSth(); //this should throw MyException
assertFail("Expected exception");
} catch (MyException e) {
//assert the message etc
}
}
again, if obj.DoSth() throws a different exception JUnit will fail the test.
So to sum up, I am afraid I believe your approach is overcomplicated, sorry.
please correct me if I am wrong. As I understood from the provided code you're only checking if there may be an exception while executing the function. But you're actually not verifying, if the called functions "works" correctly unless the only way to end in case of an error would be an exception. I suggest writing additional tests like this:
public void testTargetFunctionSomeValue() {
int someValue = 0;
callTargetFunction(someValue, someValue);
assertTrue(verifyTargetFunction(someValue, someValue));
}
public boolean verifyTargetFucntion(int someValue, int someValue) {
// verify that execution of targetFunction made expected changes.
. . . . .
}
and the verifyTargetFunction would acutally check, if calling targetFunction would have made the expected changes - let's say to a database table by returning true or false.
Hope that helps.
Cheers,
Markus