I have a method that throws exception in some cases. My unit test:
class Bob extends GroovyTestCase {
void testClusterInvalidSomeParameter() {
Abc abcClass = new Abc(2, 0)
shouldFail {
abcClass.calculate()
}
}
}
If second parameter == 0, then method throws exception: "Parameter cannot be null". How can I test that it throws exactly this exception?
shouldFail() and shouldFailWithCause() returns the cause/message of the exception. If the message/cause is set then, you can use the assertion as below:
class Bob extends GroovyTestCase {
void testClusterInvalidSomeParameter() {
Abc abcClass = new Abc(2, 0)
String message = shouldFail {
abcClass.calculate()
}
assert message == "Parameter cannot be null"
}
}
A better test would be to also assert the type of Exception thrown:
String message = shouldFail( XyzException ) {
abcClass.calculate()
}
Related
I tried many references available regarding the same but nothing worked.
I have a method in Kotlin which can throws Checked and unchecked exceptions both(depend on which block in throwing the exception)
fun deleteItem(tokens: List<String>, userId: Long) {
val records = storeRegistry.readItemsByTokens(tokens)
val missingTokens = tokens.toSet() - records.map { it.token }.toSet()
if (missingTokens.isNotEmpty()) {
throw EntityNotFoundException( // checked exception
"Item with tokens=$missingTokens does not exist."
)
}
transactionManager.executeInTransaction {
tokens.forEach {
val success = storeRegistry.deleteItemByToken(it, userId)
if (!success) {
throw InternalException.badRequest( // unchecked exception
"Item delete failed: item token=$it"
)
}
}
}
}
This method is called from some other's class method which is in test. and Unit test look like this
#Test
fun deleteItemShouldThrowIfEntityNotFound() {
whenever(ItemManager.deleteItemsByTokens(any(), any()))
.thenAnswer { throw EntityNotFoundException() }
val deleteRequest = ItemsDeleteRequest.builder()
.ItemsDeleteParams(
listOf(
ItemDeleteParams.createToken("token1"),
ItemDeleteParams.createToken("token2"),
)
).build()
// act
try {
getAfterburner().ignite(
buildServiceRequest(deleteRequest),
DEFAULT_TEST_TIMEOUT
).join()
} catch (e: Exception) {
assert(e.cause is EntityNotFoundException)
}
verify(ItemManager, times(1))
.deleteItemsByTokens(listOf("token1", "token2"), 123456L)
}
When I run above test, I got this error
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: com.abc.xtz.api.EntityNotFoundException
Mockito won't throw a checked exception for a function that doesn't have the checked exception as part of its signature. To be able to do this, you need to add the checked exception to the function signature using #Throws:
#Throws(EntityNotFoundException::class)
fun deleteItem(tokens: List<String>, userId: Long) {
//...
I have some strange error when using spock.
I mock some method, and it's worked, and the behavior is corrent. But when I want to verify if the mocked method is called, the mock will not work at all.
Here is sample code:
import spock.lang.Specification
class MockServiceSpec extends Specification {
private TestService service = Mock()
void setup() {
service.get() >> {
println "mocked method called" // print some log and it proves that this mock is realy not work in second test
return "mocked result"
}
}
def "worked perfect"() {
when:
String r = service.get()
then:
r == "mocked result"
}
def "verify if get() is called and return null"() {
when:
String r = service.get()
then:
r == null // why??
1 * service.get()
}
class TestService {
public String get() {
return "real result";
}
}
}
Both tests pass:
You are overriding the mocked method, and not providing a return value, so it results in null. Try:
def "verify if get() is called and returns exactly what it's told to"() {
when:
String r = service.get()
then:
r == "ok" // returns exactly what you mock on the next line
1 * service.get() >> "ok"
}
Currently, whenever I need to fail a test in response to an exception thrown in another thread, I write something like this:
package com.example;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;
import static java.util.Arrays.asList;
import static java.util.Collections.synchronizedList;
import static org.testng.Assert.fail;
public final class T {
#Test
public void testFailureFromLambda() throws Throwable {
final List<Throwable> errors = synchronizedList(new ArrayList<>());
asList("0", "1", "2").parallelStream().forEach(s -> {
try {
/*
* The actual code under test here.
*/
throw new Exception("Error " + s);
} catch (final Throwable t) {
errors.add(t);
}
});
if (!errors.isEmpty()) {
errors.forEach(Throwable::printStackTrace);
final Throwable firstError = errors.iterator().next();
fail(firstError.getMessage(), firstError);
}
}
}
A synchronized list may be replaced with an AtomicReference<Throwable>, but in general the code remains pretty much the same.
Is there any standard (and less verbose) way of doing the same using any of test frameworks available in Java (TestNG, JUnit, Hamcrest, AssertJ, etc.)?
By default TestNG fails a test method when an exception is thrown from it. I believe the same thing happens with JUnit as well, wherein it marks a test as errored, if it throws an unexpected exception.
If you are to be dealing with Streams, then you would need to wrap it up within a RuntimeException variant, so that Java doesn't complain. TestNG would automatically fail the test.
Here's a sample :
#Test
public void testFailureFromLambdaRefactored() {
asList("0", "1", "2").parallelStream().forEach(s -> {
try {
/*
* The actual code under test here.
*/
if (s.equals("2")) {
throw new Exception("Error " + s);
}
} catch (final Throwable t) {
throw new RuntimeException(t);
}
});
}
This was for scenarios that involve lambdas and streams. In general if you would like to know about an exception that happens in a new thread spun off from a #Test method, then you would need to use ExecutorService.
Here's a sample :
#Test
public void testFailureInAnotherThread() throws InterruptedException, ExecutionException {
List<String> list = asList("0", "1", "2");
ExecutorService service = Executors.newFixedThreadPool(2);
List<Future<Void>> futures = service.invokeAll(Arrays.asList(new Worker(list)));
for (Future future : futures) {
future.get();
}
}
public static class Worker implements Callable<Void> {
private List<String> list;
public Worker(List<String> list) {
this.list = list;
}
#Override
public Void call() throws Exception {
for (String s : list) {
if (s.equals("2")) {
throw new Exception("Error " + s);
}
}
return null;
}
}
In Java, the programmer can specify expected exceptions for JUnit test cases like this:
#Test(expected = ArithmeticException.class)
public void omg()
{
int blackHole = 1 / 0;
}
How would I do this in Kotlin? I have tried two syntax variations, but none of them worked:
import org.junit.Test
// ...
#Test(expected = ArithmeticException) fun omg()
Please specify constructor invocation;
classifier 'ArithmeticException' does not have a companion object
#Test(expected = ArithmeticException.class) fun omg()
name expected ^
^ expected ')'
The Kotlin translation of the Java example for JUnit 4.12 is:
#Test(expected = ArithmeticException::class)
fun omg() {
val blackHole = 1 / 0
}
However, JUnit 4.13 introduced two assertThrows methods for finer-granular exception scopes:
#Test
fun omg() {
// ...
assertThrows(ArithmeticException::class.java) {
val blackHole = 1 / 0
}
// ...
}
Both assertThrows methods return the expected exception for additional assertions:
#Test
fun omg() {
// ...
val exception = assertThrows(ArithmeticException::class.java) {
val blackHole = 1 / 0
}
assertEquals("/ by zero", exception.message)
// ...
}
Kotlin has its own test helper package that can help to do this kind of unittest.
Your test can be very expressive by use assertFailWith:
#Test
fun test_arithmethic() {
assertFailsWith<ArithmeticException> {
omg()
}
}
You can use #Test(expected = ArithmeticException::class) or even better one of Kotlin's library methods like failsWith().
You can make it even shorter by using reified generics and a helper method like this:
inline fun <reified T : Throwable> failsWithX(noinline block: () -> Any) {
kotlin.test.failsWith(javaClass<T>(), block)
}
And example using the annotation:
#Test(expected = ArithmeticException::class)
fun omg() {
}
You can use Kotest for this.
In your test, you can wrap arbitrary code with a shouldThrow block:
shouldThrow<ArithmeticException> {
// code in here that you expect to throw a ArithmeticException
}
JUnit5 has kotlin support built in.
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
class MyTests {
#Test
fun `division by zero -- should throw ArithmeticException`() {
assertThrows<ArithmeticException> { 1 / 0 }
}
}
You can also use generics with kotlin.test package:
import kotlin.test.assertFailsWith
#Test
fun testFunction() {
assertFailsWith<MyException> {
// The code that will throw MyException
}
}
Nobody mentioned that assertFailsWith() returns the value and you can check exception attributes:
#Test
fun `my test`() {
val exception = assertFailsWith<MyException> {method()}
assertThat(exception.message, equalTo("oops!"))
}
}
This simple sample worked in the 4.13.2 version of Junit
#Test
fun testZeroDividing(){
var throwing = ThrowingRunnable { /*call your method here*/ Calculator().divide(1,0) }
assertThrows(/*define your exception here*/ IllegalArgumentException::class.java, throwing)
}
Assert extension that verifies the exception class and also if the error message match.
inline fun <reified T : Exception> assertThrows(runnable: () -> Any?, message: String?) {
try {
runnable.invoke()
} catch (e: Throwable) {
if (e is T) {
message?.let {
Assert.assertEquals(it, "${e.message}")
}
return
}
Assert.fail("expected ${T::class.qualifiedName} but caught " +
"${e::class.qualifiedName} instead")
}
Assert.fail("expected ${T::class.qualifiedName}")
}
for example:
assertThrows<IllegalStateException>({
throw IllegalStateException("fake error message")
}, "fake error message")
org.junit.jupiter.api.Assertions.kt
/**
* Example usage:
* ```kotlin
* val exception = assertThrows<IllegalArgumentException>("Should throw an Exception") {
* throw IllegalArgumentException("Talk to a duck")
* }
* assertEquals("Talk to a duck", exception.message)
* ```
* #see Assertions.assertThrows
*/
inline fun <reified T : Throwable> assertThrows(message: String, noinline executable: () -> Unit): T =
assertThrows({ message }, executable)
Another version of syntaxis using kluent:
#Test
fun `should throw ArithmeticException`() {
invoking {
val backHole = 1 / 0
} `should throw` ArithmeticException::class
}
Firt steps is to add (expected = YourException::class) in test annotation
#Test(expected = YourException::class)
Second step is to add this function
private fun throwException(): Boolean = throw YourException()
Finally you will have something like this:
#Test(expected = ArithmeticException::class)
fun `get query error from assets`() {
//Given
val error = "ArithmeticException"
//When
throwException()
val result = omg()
//Then
Assert.assertEquals(result, error)
}
private fun throwException(): Boolean = throw ArithmeticException()
Just started using Scala for unit testing and am totally confused as to how exceptions are handled in Scala. Below is an example of a JUnit test.
class Test {
#Test
void someTest {
try {
//Something
} catch(Exception e) {
Assert.assertTrue(e.getCause() instanceOf IOException);
}
}
}
Now I want to do the same thing in Scala, I tried
class Test {
#Test def someTest {
try {
//Something
} catch {
case e: Exception => assertTrue(e.getCause().isInstanceOf[IOException])
}
}
}
But my IDE keeps complaining that Method Apply is not a member of type Any. I read about exception handling in Scala and found that you should use a pattern matcher and that there is no exception handling in Scala. How exactly does this work?
If you are testing scala code I suggest using something more scalish than jUnit like ScalaTest.
import java.io.IOException
import org.scalatest._
import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers
object SomeCode
{
def apply() = {
throw new IOException
}
}
class SomeTest
extends FlatSpec
with ShouldMatchers
{
"Something" should "throw an IOException, TODO: why ?" in
{
intercept[IOException] {
SomeCode()
}
}
it should "also throw an IOException here" in
{
evaluating { SomeCode() } should produce [IOException]
}
}
nocolor.run( new SomeTest )