Junit 5: Expected exception to be thrown, but nothing was thrown - java

I have very strange behavior for the following test:
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.NoSuchElementException;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class TestLogger {
static IPcdsLogger logger;
static Logger LOGGER = LoggerFactory.getLogger(TestLogger.class);
#BeforeEach
public void setup() {
logger = PcdsLoggerFactory.getLogger(TestLogger.class);
}
#AfterEach
public void tearDown() throws IOException {
PrintWriter writer = new PrintWriter(new File("src/test/resources/temp/test.log"));
writer.print("");
writer.close();
}
#AfterAll
public static void deleteFile() throws IOException {
logger.close();
FileUtils.deleteDirectory(new File("src/test/resources/temp"));
}
#Test
public void testJsonParams() throws IOException {
logger.builder()
.add("hello", "world")
.add("bob", "alice")
.debug("wtf");
assertEquals("world", readLine(0).get("hello"));
assertEquals("alice", readLine(0).get("bob"));
}
#Test
public void testLogLevelTraceCheck() {
logger.traceLevel()
.ifPresent(b -> b.add("hello", "world").trace());
assertThrows(NoSuchElementException.class, () -> readLine(0));
}
private JSONObject readLine(int lineNo) throws IOException {
try (Stream<String> lines = Files.lines(Paths.get("src/test/resources/temp/test.log"))) {
String line = lines.skip(lineNo).findFirst().get();
return new JSONObject(line);
}
}
When I run the test individually, it passes.
When I run all the tests, on the second run I get the following error for the testLogLevelTraceCheck:
Expected java.util.NoSuchElementException to be thrown, but nothing was thrown.
org.opentest4j.AssertionFailedError: Expected java.util.NoSuchElementException to be thrown, but nothing was thrown.
at app//org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:71)
at app//org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
at app//org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3082)
I thought it was enough to reinstantiate the logger in #BeforeEach, but somehow it doesn't happen all the time this.
Do you have any suggestions?

If it does not throw, it could mean that the file is actually there and has some content. This makes sense, since just calling PcdsLoggerFactory.getLogger(TestLogger.class) does not seem to guarantee to delete the logfile then.

Related

Mockito Junit 5 Throw checked exception not working

I am trying to throw SQLException during a method call. But the exception is not thrown for some reason.
Error message
org.opentest4j.AssertionFailedError: Expected java.sql.SQLException to be thrown, but nothing was thrown.
at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:71)
at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:2952)
I would like the exception to be thrown when dropRun() is invoked
public interface RunRepository {
void dropRun(List<Integer> ids) throws SQLException;
}
Its Implementation
public class RunRepositoryImpl implements RunRepository{
#Override
public void dropRun(List<Integer> ids) throws SQLException {
//some piece of code
}
}
The Class I would like to test
public interface Project {
void purge() throws SQLException;
}
and its Implementation
public ProjectImpl implements Project{
#Override
public void purge() throws SQLException {
//some piece of code
try {
runRepository.dropRun(ids);
} catch (Exception e) {
LOGGER.error("Error purging completed runs.");
throw e;
}
}
}
Test class
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kfj.repository.RunRepository;
import com.kfj.service.Project;
import java.sql.SQLException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
#TestInstance(Lifecycle.PER_CLASS)
#ExtendWith(MockitoExtension.class)
public class ProjectImplTest {
private Project project;
#Mock
private RunRepository runRepository;
#BeforeEach
public void setUp() {
//some piece of code
project = new ProjectImpl(runRepository);
}
#Test
public void GIVEN_non_empty_completed_runs_WHEN_purge_is_invoked_THEN_dropRun_is_invoked()
throws SQLException {
//MOCK Trail 1 DIDN'T WORK
//doThrow(SQLException.class).when(runRepository).dropRun(any());
//MOCK Trail 2 DIDN'T WORK either
willAnswer(invocation -> {
throw new SQLException();
}).given(runRepository).dropRun(any());
//Then
assertThrows(SQLException.class, () -> project.purge());
}
}
I tried a couple of links, but no luck!. Any help would be highly appreciated. TIA.
Link1
Link2
I am facing the same issue, The following code doens't work.
JUnit fails with
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: javax.xml.bind.JAXBException: aa
DocumentService documentService = mock(DocumentService.class);
#Test
#DisplayName("Returns 500 http status when we have an error calling the PFEL")
void handle_document_create_request_exception_in_service() {
willThrow(new JAXBException("aa")).given(documentService).generateDocument(any(DocumentCreateDto.class));
}
But if I replace the CheckedExcpetion with a RunTime exception, it works as expcected

Testing println output with JUnit

I am testing a simple helloWorld class.
package Codewars;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
And I have a test class as follows (based on the answer ):
import static org.junit.jupiter.api.Assertions.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class helloWorldTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final PrintStream originalOut = System.out;
#BeforeEach
public void setUpStreams() {
System.setOut(new PrintStream(outContent));
}
#AfterEach
public void restoreStreams() {
System.setOut(originalOut);
}
#Test
void test() {
HelloWorld.main(null);
assertEquals("Hello World\n", outContent.toString());
}
}
It results in failure with error message as follows:
org.opentest4j.AssertionFailedError: expected: <Hello World
> but was: <Hello World
>
at org.junit.jupiter.api#5.5.1/org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
at org.junit.jupiter.api#5.5.1/org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
...
It seems like the strings are same and still the error is thrown?
Thank you in advance.
Make sure that your line separator is equal to \n on your system.
This is not the case on Windows.
To fix the test, modify it to take system-specific separator into account
assertEquals("Hello World" + System.lineSeparator(), outContent.toString());

In junit 4 #Beforeclass #Before and #After tests cases: wrong order of execution

I am trying to run some simple tests using Junit 4 library and am using #Before, #After, and #BeforeClass annotations. But the problem is #Before and #After are being executed before the #BeforeClass. why is that?
Code:
import junit.runner.Version;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestClass2
{
#BeforeClass
public static void before() throws Exception
{
System.out.println("Before class");
}
#Before
public void setUp() throws Exception
{
System.out.println("Before");
}
#After
public void tearDown() throws Exception
{
System.out.println("After");
}
#Test
public void name() throws Exception
{
System.out.println("Test");
System.out.println("JUnit version is: " + Version.id());
}
}
Output:
Before
Test
JUnit version is: 4.12
After
Before class
Process finished with exit code 0
Make sure you declare the #BeforeClass method as static, and using JUnit's annotation (not TestNG). A full code exmaple:
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* #author sainnr <p/>27.12.2017.
*/
public class TestClass {
#BeforeClass
public static void before() throws Exception {
System.out.println("Before class");
}
#Before
public void setUp() throws Exception {
System.out.println("Before");
}
#After
public void tearDown() throws Exception {
System.out.println("After");
}
#Test
public void name() throws Exception {
System.out.println("Test");
}
}
Output:
Before class
Before
Test
After
As per JUnit documentation: http://junit.sourceforge.net/javadoc/org/junit/BeforeClass.html.

How to configure JUnit rules to apply to specific test

Is it possible to have a Junit rule only apply to specific tests? If so, how do I do that?
The code below exemplifies what I want to do: each time I have #Rule, I want the method below that to have the specific rule that has been annotated to run with it. I only want that rule to run with the corresponding test. I don't want anything other tests to be affected by the rule.
In this case, when I run these tests, I see that one of the tests the EmptyFileCheck, gives a File DNE does not exist, but I have used a separate annotation for that function, so I had thought that it would run with a different context, supplying the Empty, but instead DNE is till being used.
import static java.lang.System.in;
import static java.lang.System.setIn;
import static org.junit.Assert.fail;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.nio.channels.Pipe;
import static org.hamcrest.core.AllOf.allOf;
import org.hamcrest.Matcher;
import org.hamcrest.core.AllOf;
import static org.hamcrest.Matchers.*;
import org.hamcrest.text.StringContains;
import org.hamcrest.text.StringEndsWith;
import org.hamcrest.text.StringStartsWith;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.TextFromStandardInputStream;
import org.junit.runner.RunWith;
public class UnitTests {
private Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
private main mn;
private InputStream oldIn;
private PrintStream oldOut;
private InputStream mockIn;
private InputStreamReader mockinputStream;
private PrintStream mockOut;
private BufferedReader reader;
private Expectations exp;
#Before
public void setMinimalMockingExpectations() throws IOException {
exp = new Expectations() {{ }};
mn = context.mock(main.class);
mockinputStream = context.mock(InputStreamReader.class);
oldIn = System.in;
oldOut = System.out;
mockIn = context.mock(InputStream.class);
mockOut = context.mock(PrintStream.class);
System.setOut(mockOut);
}
public void configureExpectations(boolean fileOrInput, boolean verbosity) {
exp.one(mockOut).println("Do you want to process standard (I)nput, or a (F)ile? I/F");
if (fileOrInput) { //it's a file
exp.one(mockOut).println("Enter filename: ");
} else { //it's not
}
}
#After
public void reset() {
System.setOut(oldOut);
}
#Rule
public final TextFromStandardInputStream FileNotFoundException
= new TextFromStandardInputStream("F\nDNE\n");
#Test(expected=FileNotFoundException.class)
public void EnsureFileCheckExists() throws IOException {
final String fileName = "DNE";
configureExpectations(true, false);
exp.one(mn).checkFile(fileName);
context.checking(exp);
mn.main(null);
}
#Rule
public final TextFromStandardInputStream FileReadAccessDenied
= new TextFromStandardInputStream("F\nUnderPriviledged\n");:w
#Test(expected=FileNotFoundException.class)
public void FileReadAccessDenied() throws java.io.FileNotFoundException {
final String fileName = "UnderPriviledged";
configureExpectations(true, false);
//exp.oneOf(mn).checkFile(with()); TODO: fix ME!
context.checking(exp);
mn.main(null);
}
#Rule
public final TextFromStandardInputStream EmptyFileCheck
= new TextFromStandardInputStream("F\nEmpty\n");
#Test
public void EmptyFileCheck() throws java.io.FileNotFoundException {
final String fileName = "Empty";
configureExpectations(true, false);
exp.one(mn).checkFile(fileName);
context.checking(exp);
mn.main(null);
}
}
You could have a setter in your Rule which is the first thing that gets called in the rule. Something like this, from ExpectedException:
// These tests all pass.
public static class HasExpectedException {
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void throwsNothing() {
// no exception expected, none thrown: passes.
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
thrown.expectMessage(startsWith("What"));
throw new NullPointerException("What happened?");
}
}
Any reason not to just take the code out of the #rule annotation and move it to the start of the test body?

Is it possible to use partial mocking for private static methods in PowerMock?

From the examples on the PowerMock homepage, I see the following example for partially mocking a private method with Mockito:
#RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
#PrepareForTest(PartialMockClass.class)
public class YourTestCase {
#Test
public void privatePartialMockingWithPowerMock() {
PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());
// use PowerMockito to set up your expectation
PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");
// execute your test
classUnderTest.execute();
// Use PowerMockito.verify() to verify result
PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");
}
However, this approach does not seem to work when the private method we wish to mock is static. I wish to create a partial mock of the below class, with the readFile method mocked:
package org.rich.powermockexample;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import static com.google.common.io.Files.readLines;
public class DataProvider {
public static List<String> getData() {
List<String> data = null;
try {
data = readFile();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
private static List<String> readFile() throws IOException {
File file = new File("/some/path/to/file");
List<String> lines = readLines(file, Charset.forName("utf-8"));
return lines;
}
}
Please could someone let me know how this can be achieved?
After doing a bit more research, it seems that PowerMockito.spy() and PowerMockito.doReturn() are what is required here:
package com.richashworth.powermockexample;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
#RunWith(PowerMockRunner.class)
#PrepareForTest({DataProvider.class})
public class ResultsWriterTest {
private static List<String> mockData = new ArrayList<String>();
private ResultsWriter resultsWriter;
#BeforeClass
public static void setUpOnce() {
final String firstLine = "Line 1";
final String secondLine = "Line 2";
mockData.add(firstLine);
mockData.add(secondLine);
}
#Before
public void setUp() {
resultsWriter = new ResultsWriter();
}
#Test
public void testGetDataAsString() throws Exception {
PowerMockito.spy(DataProvider.class);
PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile");
final String expectedData = "Line 1\nLine 2\n";
final String returnedString = resultsWriter.getDataAsString();
assertEquals(expectedData, returnedString);
}
}
For further details and the complete code listing, check out my blog post here: https://richashworth.com/post/turbocharge-your-mocking-framework-with-powermock/
Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(DataProvider.class)
public class DataProviderTest {
#Test
public void testGetDataWithMockedRead() throws Exception {
mockStaticPartial(DataProvider.class, "readFile");
Method[] methods = MemberMatcher.methods(DataProvider.class, "readFile");
expectPrivate(DataProvider.class, methods[0]).andReturn(Arrays.asList("ohai", "kthxbye"));
replay(DataProvider.class);
List<String> theData = DataProvider.getData();
assertEquals("ohai", theData.get(0));
assertEquals("kthxbye", theData.get(1));
}
}
Class being tested (basically yours):
public class DataProvider {
public static List<String> getData() {
try {
return readFile();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static List<String> readFile() throws IOException {
File file = new File("/some/path/to/file");
return readLines(file, Charset.forName("utf-8"));
}
}
In general, only use static mocking for classes that are beyond your control (e.g. java.io.File). Since DataProvider and readFile are your own, refactor DataProvider into a proper class (i.e. make its methods non-static), pull out readFile into a helper object and then mock that. See this answer https://stackoverflow.com/a/8819339/116509.

Categories