I am confused on this JUnit Test Case - java

new to Java programming, I am just trying to understand how I can make this class be tested. I have made a Queue class:
public class Queue<E> {
private ArrayList<E> items;
public Queue(){
items = new ArrayList<E>();
}
public void join(E e) {
items.add(e);
}
public E leave() throws EmptyQueueError {
if (items.isEmpty()) {
throw new EmptyQueueError();
}
return items.remove(0);
}
}
I want to make a JUnit called QueueTest that is automatically reset to empty before each test that is commenced? Then I want it check that removing an item from an empty queue throws an EmptyQueueError? Finally, I want it to check that when several items join an (initially) empty queue, it is the first item that joined which is the first to leave?
It's a tutorial I am following but it fails to make me understand. I have made the class above and I have attempted the JTest class:
package queue;
public class QueueTest<e> {
private Queue q;
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void test() {
q = new Queue<e>();
assertEquals("Empty Queue", 0, q);
}
}
Am I close to what I am trying to achieve? I am trying to do the first one.
Thank you for your help and ample time.

You're doing well.
#Test
public void test() {
q = new Queue<e>();
assertEquals("Empty Queue", 0, q);
}
The problem with this is that you make a new Queue instance, but you don't do anything with it.
Then your test's innards could be
#Test
public void test() {
Queue<Integer> q = new Queue<Integer>(); // A
try {
Integer ignore = q.leave(); // B
fail("exception expected"); // C
} catch (EmptyQueueError ex) {
// implicit success // D
}
}
What this means is that you'd make a Queue ('A'), then immediately try to get an item ('B'). This should cause an exception. If it does not, your test fails with "exception expected" ('C'). If the expected exception is thrown, you code works ('D')
I'll post more once you get this working.

Try this: they run for me. You aren't far off.
package cruft;
import java.util.ArrayList;
public class Queue<E> {
private ArrayList<E> items;
public Queue(){
items = new ArrayList<E>();
}
public void join(E e) {
items.add(e);
}
public E leave() throws EmptyQueueError {
if (items.isEmpty()) {
throw new EmptyQueueError();
}
return items.remove(0);
}
// Note: I added this.
public int size() { return this.items.size(); }
}
}
And here's the test:
package cruft;
import org.junit.Assert;
import org.junit.Test;
public class QueueTest {
#Test
public void test() {
Queue<String> q = new Queue<String>();
Assert.assertEquals("queue should be empty", 0, q.size());
}
}
Notice: You should just create an instance in the test. Make sure your queue has a concrete type of thing to hold (String in this case).
Remember what generics are doing for you: they let you create a collection or container whose behavior doesn't depend on the type of objects it holds onto. So you might have a Queue that contains Strings or Persons or Penguins.

So what are you trying to test here? When you do assertEquals("Empty Queue", 0, q) what are you attempting to test here? That the Queue is empty?
For the asserts what they usually take is something to test, IE Q == 0, and they take an optional message, which will be printed out if the test fails.
The flaw in why your assertEquals fails is something that you can see by investigating what the value of q is.

Here is how to do it with TestNG, showing how to test an exception and how to reset the queue before each test method:
public class QueueTest {
private Queue q = new Queue();
#BeforeMethod
public void setUp() throws Exception {
q.reset();
}
#Test(expectedExceptions = EmptyQueueError.class)
public void shouldThrowIfRemovingFromEmpty() {
assertTrue(q.isEmpty());
q.remove(0);
}
}
If you want to be very strict, you should probably test that each queue is initially empty and the exception in two separate test methods.

Related

public void method throws Exception if - JUNIT test: Exception should not be thrown

I have a certain public void method which throws an Exception if a condition is fulfilled.
In my case the method looks like this:
public void toBeTestedMethod(Testobject testObject) throws CertainException {
if (testObject.getStatus().getAllowsEdit()){
throw ...}
}
getStatus() is a method which returns a certain Status and getAllowsEdit() is a method which returns a boolean value and nullable = true. For the two methods there also exist set-methods.
Edit1: The test regarding this method when it fails is already running fine:
public void testToBeTestedMethod_FailureStatus() throws Exception {
try {
TestObject testObject = _testObjectMockDAO.getNewTestObject();
_testObjectMockDAO.setTestObject(testObject);
_testObjectBusinessImpl.toBeTestedMethod(testObject);
fail("Check failed");
} catch (CertainException ex) {
assertEquals(ErrorCode.WRONG_STATUS, ex.getErrorCode());
}
}
I would now like to test the method toBeTestedMethod. The target is that the method does not throw an exception but gets executed successfully.
That means I would like to write a JUNIT-test which tests the following:
public void testToBeTestedMethod_success throws Exception{
// Enter test code here
}
Edit2 (regarding the class Status):
public class Status {
...
private String _status;
public String getStatus() {
return _status;
}
}
In my opinion, I have to modify the condition in the if-statement in order to get the expected result, correct?
Note: I did not write the method and the other code. Nevertheless, my task is to test the code via JUNIT.
I tried some code, but everytime I get the error that the Excpetion was thrown.
Even if you cannot solve this problem, I would be glad to get some hints where I should look for the problem why my test does not do what I want the test to do.
Your question is very abstract and needs more data, I am posting an answer here based on what I have understood.
Here are the classes:
public class SampleTestService {
public boolean toBeTestedMethod(TestObject testObject) throws AccessViolationException {
if (testObject.getStatus().getAllowsEdit()) {
throw new AccessViolationException("Edit is allowed for this non confirmed user");
} else {
return true;
}
}
static class TestObject {
private SomeStatus someStatus;
public SomeStatus getStatus() {
return someStatus;
}
}
static class SomeStatus {
private boolean allowsEdit;
public boolean getAllowsEdit() {
return allowsEdit;
}
}
static class AccessViolationException extends RuntimeException {
public AccessViolationException(String message) {
super(message);
}
}
}
Since the method depends on another class and that class-dependent also on another class you need to mock them in the chain. Here is how I have done it:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
#ExtendWith(SpringExtension.class)
class SampleTestServiceTest {
private final SampleTestService.TestObject mockTestObject = mock(SampleTestService.TestObject.class);
private final SampleTestService.SomeStatus mockSomeStatus = mock(SampleTestService.SomeStatus.class);
private final SampleTestService service = new SampleTestService();
#Test
void testThatMethodDoesNotThrowsException() {
when(mockTestObject.getStatus()).thenReturn(mockSomeStatus);
when(mockSomeStatus.getAllowsEdit()).thenReturn(false);
boolean result = service.toBeTestedMethod(mockTestObject);
Assertions.assertTrue(result);
}
#Test
void testThatMethodThrowsException() {
when(mockTestObject.getStatus()).thenReturn(mockSomeStatus);
when(mockSomeStatus.getAllowsEdit()).thenReturn(true);
Assertions.assertThrows(SampleTestService.AccessViolationException.class, () -> {
service.toBeTestedMethod(mockTestObject);
});
}
}

Mock another method in SWF Workflow Client

I am trying to write a unit test for a AWS SWF workflow. Below is the code I would like to Test
#Override
public void execute(String abc) {
new TryCatch() {
#Override
protected void doTry() throws Throwable {
Promise<SomeObject> temp = activityClient.action(abc);
again(temp, abc);
}
#Override
protected void doCatch(Throwable e) throws Throwable {
throw new RuntimeException(e);
}
};
}
#Asynchronous
public void again(Promise<SomeObject> someObject, String abc) {
// Do Something
}
My Test class is as below:
public class SomeWorkflowTest extends AbstractTestCase {
#Rule
public WorkflowTest workflowTest = new WorkflowTest();
List<String> trace;
private SomeWorkflowClientFactory workflowFactory = new SomeWorkflowClientFactoryImpl();
#Before
public void setUp() throws Exception {
trace = new ArrayList<String>();
// Register activity implementation to be used during test run
SomeActivitiesImpl activitiesImpl = new SomeActivitiesImpl() {
#Override
public SomeObject performHostRecovery(String abc) {
trace.add("ABC: " + abc);
SomeObject testObject = new SomeObject();
return testObject;
}
};
workflowTest.addActivitiesImplementation(activitiesImpl);
workflowTest.addWorkflowImplementationType(SomeWorkflowImpl.class);
}
#Test
public void testWorkflowExecutionCall() throws Throwable {
SomeWorkflowClient workflow = workflowFactory.getClient("XZY");
workflow.execute("XYZ");
List<String> expected = new ArrayList<String>();
expected.add("ABC: abc");
AsyncAssert.assertEqualsWaitFor("Wrong Wrong", expected, trace, null);
}
}
I have used SWF Testing Docs to write above test class. However the method that I am testing (execute()) is invoking another method in same class. I am not concerned with the execution of internal method and would like to mock it out, but given the way the workflow class object is instantiated, I am not clear on how to mock the inner method.
Can someone please point out on this?
Thanks
You actually can instantiate a workflow object or any other object that workflow uses inside the test method:
#Test
public void testWorkflowExecutionCall() throws Throwable {
SomeWorkflow workflow = new SimpleWorkflow(...);
workflow.execute("XYZ");
List<String> expected = new ArrayList<String>();
expected.add("ABC: abc");
AsyncAssert.assertEqualsWaitFor("Wrong Wrong", expected, trace, null);
}
It works because WorkflowTest executes test methods in the context of a dummy test workflow. The code
SomeWorkflowClient workflow = workflowFactory.getClient("XZY");
workflow.execute("XYZ");
actually creates a child workflow in the context of this dummy workflow. But nothing prevents you from executing any async code directly without creating the child workflow.

Mocking chained methods calls using PowerMock

I have a class which I would like to test with a public static method that contains some chained method calls. Assuming that an exception occurs during the chained method calls, how do I handle this effectively and make it return some specific value?
Following is the code sample of the test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class,CodeWithYetAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = PowerMockito.spy(new CodeWithYetAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithYetAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithYetAnotherPrivateMethod);
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
PowerMockito.doReturn(true).when(codeWithYetAnotherPrivateMethod, "getGambling");
//PowerMockito.doReturn(codeWithYetAnotherPrivateMethod).when(codeWithAnotherPrivateMethod, "getGambleValue");
PowerMockito.spy(CodeWithPrivateMethod.class);
CodeWithPrivateMethod.startGamble();
}
}
Following is the code sample for the class under test
public class CodeWithPrivateMethod {
public static void startGamble() {
Boolean gamble = CodeWithAnotherPrivateMethod.getGambleValue()
.getGambling();
if (gamble) {
System.out.println("kaboom");
}else{
System.out.println("boom boom");
}
}
}
Following is the code sample for the class that gets called from the class under test
public class CodeWithAnotherPrivateMethod {
static CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = new CodeWithYetAnotherPrivateMethod();
public static CodeWithYetAnotherPrivateMethod getGambleValue() {
return codeWithYetAnotherPrivateMethod; //works fine
return null; // fails
}
}
Following is the code sample for the other class that gets called from the class under test
public class CodeWithYetAnotherPrivateMethod {
public Boolean getGambling() {
return false;
}
}
So Assuming I return a null value from getGambleValue() method of CodeWithAnotherPrivateMethod class, how do I handle this null value effectively in my testclass?
This is how to specify expected exceptions using Mockito:
#Test(expected = NullPointerException.class)
public void when_gambling_is_true_then_always_explode() throws Exception {
...
Before I found out about this I would do:
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
// setup omitted
try {
CodeWithPrivateMethod.startGamble();
}
catch(NullPointerException e) {
// expected
return;
}
fail("Expected NullPointerException");
}
EDIT: Testing multiple classes that call each other statically like this is a severe code smell. Unit tests should test a single class and inline static calls should be limited to utility classes.
Another comment: your example class names are very confusing. Next time please stick with Foo, Bar, Baz or Appple, Pear, Banana.
If you are not getting an NPE then I expect your mocking/spying is interfering. If you call the code under test without mocking/spying the call chain would be:
CodeWithPrivateMethod.startGamble();
->
CodeWithYetAnotherPrivateMethod value = CodeWithAnotherPrivateMethod.getGambleValue();
->
return null;
<-
value.getGambling();
<- throws NullPointerException
What exactly are you trying to find out or achieve?
EDIT: Here's how it should work with PowerMock
#RunWith(PowerMockRunner.class)
#PrepareForTest(CodeWithAnotherPrivateMethod.class)
public class CodeWithPrivateMethodTest {
#Mock
private CodeWithYetAnotherPrivateMethod yetAnotherInstance;
#Test
public final void testStartGamble() {
// SETUP
mockStatic(CodeWithAnotherPrivateMethod.class);
expect(CodeWithAnotherPrivateMethod.getGambleValue())
.andReturn(yetAnotherInstance);
Boolean gamblingValue = true;
expect(yetAnotherInstance.getGambling()).andReturn(gamblingValue);
replayAll();
// CALL
CodeWithPrivateMethod.startGamble();
// VERIFY
verifyAll();
}

TestNG expectedExceptions throws TestException

I am trying to test the following class:
package com.myclass;
public class MyClass {
private Map<String, String> dataMap = new HashMap<>();
public void extractInfoFromLine(String line) throws InvalidInputException {
String[] words = line.split(" ");
if (dataMap.containsKey(words[0])) {
throw new InvalidInputException();
}
dataMap.put(words[0], words[2]);
}
public void confirmInfoPresent(String name) {
// Do something
}
}
Using this TestNG class:
package com.myclass;
public class MyClassTest {
private MyClass myClass;
#DataProvider(name = "invalid-data-provider")
public Object[][] invalidDataProvider() {
return new Object[][] {
{ "A is B", "A"},
{ "A is D", "A"},
};
}
#BeforeTest()
public void setup() {
myClass = new MyClass();
}
#Test(dataProvider = "invalid-data-provider", expectedExceptions = InvalidInputException.class)
public void testExceptionalExtractValueForKey(String line, String name) throws InvalidInputException {
myClass.extractInfoFromLine(line);
myClass.confirmInfoPresent(name);
}
}
I have defined the following custom exception for this:
package com.myclass;
public class InvalidInputException extends Exception {
public InvalidInputException() {
super();
}
public InvalidInputException(String message) {
super(message);
}
public InvalidInputException(String message, Throwable cause) {
super(message, cause);
}
public InvalidInputException(Throwable cause) {
super(cause);
}
}
However, when I run this test case, I get the following error:
Expected exception com.myclass.InvalidInputException but got org.testng.TestException:
Method MyClassTest.testExceptionalExtractValueForKey(java.lang.String, java.lang.String)[pri:0, instance:com.myclass.MyClassTest#3930015a] should have thrown an exception of class com.myclass.InvalidInputException
I tried replacing my custom exception with a standard exception and still got the same result.
Can someone please help me with this?
#KarthickS, three different people gave you same answer already. I don't understand what else should be explained and how.
On the first #Test iteration dataMap is empty (dataMap.containsKey(words[0]) == false), so, the code inside "if" statement body will not be executed; which means that your exception will not be thrown.
TestNg will threat the test as failed since there is "expectedExceptions" attribute set in your #Test annotation. The second test iteration will pass since dataMap is not empty anymore (dataMap.put(words[0], words[2]) - you've added data on the first run).
Once again, TestNg doc says about "expectedExceptions": The list of exceptions that a test method is expected to throw. If no exception or a different than one on this list is thrown, this test will be marked a failure.

Mockito & Junit null pointer exception: name must not be null

I have been trying to run the following test using mockito and junit and I keep on getting "java.lang.NullPointerException: name must not be null"
Can anyone tell me why this is happening?
On debugging, I found out that this exception is thrown when the test executes the following statement in isStopValid(String) method:
FacilityValidationUtil facUtil = new FacilityValidationUtil();
#RunWith(MockitoJUnitRunner.class)
public class MyFormTest{
#InjectMocks MyForm form = new MyForm();
#Mock FacilityValidationUtil facUtil;
#Test
public void testIsStopValid() throws FinderException{
when(facUtil.isFacilityValid("")).thenReturn(false);
form.setOrigin("");
assertEquals(false, form.isStopValid(form.getOrigin()));
}
}
Class with method to be tested:
public class MyForm{
FacilityValidationUtil facUtil = new FacilityValidationUtil();
public boolean isStopValid(String stop){
try {
return facUtil.isFacilityValid(stop);
} catch (FinderException e) {
log.error("Error finding the stop. "+e.getCause());
return false;
}
}
}
public class FacilityValidationUtil{
private FacilityDAO facilityDao = new HibernateFacilityDAO();
public boolean isFacilityValid(String facility) throws FinderException{
boolean test;
FacilityImpl facilityImpl = facilityDao.findFacilityByNassCode(facility);
test = (facilityImpl==null)?false : true;
return test;
}
}
public class HibernateFacilityDAO extends HibernateAbstractDeltaDAO implements FacilityDAO {
public HibernateFacilityDAO() {
super(false);
}
}
Short Answer: You are trying to mock a variable (facUtil) that is local to your isStopValid method, so the mock version of this object in your test is never going to be called because you are 'newing it up" each time.
Long Answer: It looks like you are trying to mock the call to your FacilityValidationUtil class, and if this is the case, then you need to either make the class a field so that Mockito can inject the object by reflection (if this object is thread safe, which it looks like it is) or explore a mocking framework like PowerMockito that will allow you to mock a constructor (google for PowerMockito when new).
PowerMockito.whenNew(FacilityValidationUtil.class).withNoArguments().thenReturn(facUtil);
Mockito doesn't support any mocking of constructor args by default.
EDIT
If you are still having trouble, then I would suggest starting with a smaller example. I've put together one for you that works and uses the code you are trying to test (It's using inner classes though, which Mockito has some quirky rules about, but I'm just doing it to compress the example).
#RunWith(MockitoJUnitRunner.class)
public class MyFormTest {
#InjectMocks
private MyForm form = new MyForm();
#Mock
private FacilityValidationUtil facUtil;
#Test
public void testIsStopValid_false() {
when(facUtil.isFacilityValid("")).thenReturn(false);
assertEquals(false, form.isStopValid(""));
}
#Test
public void testIsStopValid_true() {
when(facUtil.isFacilityValid("")).thenReturn(true);
assertEquals(true, form.isStopValid(""));
}
public class MyForm {
private FacilityValidationUtil facUtil = new FacilityValidationUtil();
public boolean isStopValid(String stop) {
try {
return facUtil.isFacilityValid(stop);
} catch (FinderException e) {
return false;
}
}
}
public class FacilityValidationUtil {
public boolean isFacilityValid(String facility) throws FinderException {
throw new RuntimeException(facility);
}
}
public class FinderException extends RuntimeException {
public FinderException(String message) {
super(message);
}
}
}
What's really important is that your mock is not getting injected correctly. Until you get that resolved, you are going to keep getting the same error. Set a break point in your MyForm at the point you call facUtil.isFaciltyValid and look at the object. It should be a mockito object, not your class.
Good luck.

Categories