Junit 5 : AssertionFailedError: expected: <true> but was: <false> - exception

I'm trying to write a unit test case for the below function in the service class
#Service
public class currencyHandler {
public boolean isNoDecimal(String currency) {
return "JPY".equalsIgnoreCase(currency) || "KRW".equalsIgnoreCase(currency);
}
}
Below is the unit case:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.svc.it.handlers;
#ExtendWith(SpringExtension.class)
public class CurrencyTests {
#Mock
CurrencyHandler currencyHandlerTest;
#Test
public void isNoCurrency() throws Exception {
assertTrue(currencyHandlerTest.isNoCurrency("ABC"));
assertTrue(currencyHandlerTest.isNoCurrency("XYZ"));
assertFalse(currencyHandlerTest.isNoCurrency("BOGUS"));
assertFalse(currencyHandlerTest.isNoCurrency(""));
assertFalse(currencyHandlerTest.isNoCurrency(null));
}
}
Below is the error when I run above unit test case:
org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:40)
at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:35)
at org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:162)
I guess I'm doing something wrong with #Mock object.
Appreciate your help. Thanks in advance!

To write a unit test for the CurrencyHandler class, you must test against an instance of that class. You must not test against an instance of a mock of that class.
The following shows how to write such a unit test.
package example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class CurrencyHandlerTests {
private CurrencyHandler currencyHandler = new CurrencyHandler();
#Test
void isNoDecimal() {
assertTrue(currencyHandler.isNoDecimal("JPY"));
assertTrue(currencyHandler.isNoDecimal("KRW"));
assertFalse(currencyHandler.isNoDecimal("BOGUS"));
assertFalse(currencyHandler.isNoDecimal(""));
assertFalse(currencyHandler.isNoDecimal(null));
}
}
To better understand the concepts here, I recommend that you read some articles or books on unit testing, mocks, and the SUT (subject under test).
In addition, you do not need to register the SpringExtension if you are writing a pure unit test like the one above, since a pure unit test does not need to interact with components in a Spring ApplicationContext.

Related

How to use mockito's matcher to call specified method when anyInt() not worked

I am new to mockito. when I use it with junit, I found anyInt() not working, the example code is as following:
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class MockitoDemo {
#Test
public void verify_doB_method_invoked() {
MockitoAnyIntMatcherDemo mockitoAnyIntMatcherDemo = Mockito.mock(MockitoAnyIntMatcherDemo.class);
when(mockitoAnyIntMatcherDemo.doA(anyInt())).thenReturn(1);
verify(mockitoAnyIntMatcherDemo, times(1)).doB(anyInt());
}
}
class MockitoAnyIntMatcherDemo {
public int doA(int a) {
return doB(a);
}
public int doB(int b) {
return b;
}
}
Any help would be appreciated。
TLDR: You never called doA in your test.
when method is used for stubbing - it is like recording expected calls and answers to them.
You successfully stubbed doA method - you recorded the expectation: "if doA is called in the test with any int argument, then return 1".
As you never called doA in your test, verify rightfully reports it was not called.
On top of that - in the example you provided you mock the object under test.
This is not what mocking is typically used for.

junits failing with easymock

I am using EasyMock to write unit tests for my blackjack game.
But I get java.lang.IllegalArgumentException: Cannot subclass final class class com.blackjack.game.cards.Card error.
Although, I feel I am doing it the right way.
Here is my testclass :
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.EasyMockSupport;
#RunWith(EasyMockRunner.class)
public class handTest extends EasyMockSupport{
private Hand hand;
private Card seven, nine, ten, jack, ace;
#Before
public void setUp() throws Exception
{
seven = EasyMock.createNiceMock(Card.class);
EasyMock.expect(seven.getValue()).andStubReturn(7);
EasyMock.expect(seven.toString()).andStubReturn("seven value: 7");
}
#Test
public void testTotalHandValueByAddingNumbers() {
replayAll();
hand.addCard(seven);
assertEquals(27, hand.getTotal());
}
}
I would be glad, if somebody could help me run this. It's been a while since I have written unit tests.
Edit: I have both of Objenesis and cglib in my classpath.
Thanks
Are you sure you have the other libraries required for class mocking?
cglib (2.2) and Objenesis (1.2) must be in the classpath to perform class mocking
In all probability your class com.blackjack.game.cards.Card is final class
and createNiceMock or in that sense EasyMock cannot be used to mock the final classes.
You will need to use Powermock for this case, have a look at this resource for more inputs https://dzone.com/articles/mock-final-class#mock-final-class
Hope this helps!
Good luck!

Is it possible to name a test suite in JUnit 4?

In JUnit3, one would could name a test suite like this:
public static Test suite() {
TestSuite suite = new TestSuite("Some test collection");
suite.addTestSuite(TestX.class);
return suite;
}
Is there an equivalent way to do this in JUnit4?
Thanks.
EDIT
Thank you, I actually managed to get it working. My question was if there is a JUnit4 equivalent way of specifying the name/description of a test suite, like in JUnit3 with "Some test collection".
Some background:
I'm converting junit tests in legacy code to the version 4, and I don't want to lose any information if possible. I apologize, I should really have been more specific in the original question.
You can do this with the Suite runner #RunWith(Suite.class):
#RunWith(Suite.class)
#SuiteClasses({Test1.class, Test2.class, TestX.class})
public class MySuite {}
Where Test1, Test2, TestX contain your tests
ref. RunWith, Suite
update:
WRT changing the actual description of your suite, I don't think there's a way to do it out-of-the-box (if there is I haven't seen it yet). What you can do, is to define your own runner with a custom description [update2]:
#RunWith(DescribedSuiteRunner.class)
#SuiteClasses({Test1.class, Test2.class, TestX.class})
#SuiteDescription("Some test collection")
public class MySuite {}
public class DescribedSuiteRunner extends Suite {
// forward to Suite
public DescribedSuiteRunner(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
super(klass, builder);
}
#Override
protected String getName() {
return getTestClass()
.getJavaClass()
.getAnnotation(SuiteDescription.class)
.value();
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface SuiteDescription {
String value();
}
The default implementation of getName just returns the class being tested's name
Yes, In JUnit 3.x, the JUnit methods had to be specifically named. They needed to begin with the word test in order for JUnit to run that as a test case. Now you can just use the #Test annotation:
#Test
public void thisIsMyTest() {
// test goes here
}
Also in JUnit4 you can state if you want some tests to run before or after all the tests in this class are invoked:
#Before
public void init() throws Exception {
System.out.println("Initializing...");
}
#After
public void finish() throws Exception {
System.out.println("Finishing...");
}
Further comparisons between JUnit3 and JUnit4 here and here.
Edit: after blgt's comment, I see I might have misunderstood your intent.
You are probably looking for #RunWith(Suite.class) - When a class is annotated with #RunWith, JUnit will invoke the class in which is annotated so as to run the tests, instead of using the runner built into JUnit. Full example of usage is here, tl;dr below:
#RunWith(Suite.class)
#SuiteClasses({ FirstTest.class, SecondTest.class })
public class AllTests {
...
}

jmockit mocked constructor not returning expected value

I am trying to unit test a class where one of its methods returns an instance of a collaborator class: depending on the values of its arguments it either returns a newly created instance, or a saved, previously created instance.
I mock the constructor call in an Expectations and set the result to a value that is a mocked instance of the collaborator. But when I test the method with parameter values that cause it to create a new instance, the mocked constructor, and therefore the method, does not return the expected value.
I have simplified this down to the following:
package com.mfluent;
import junit.framework.TestCase;
import mockit.Expectations;
import mockit.Mocked;
import mockit.Tested;
import org.junit.Assert;
import org.junit.Test;
public class ConstructorTest extends TestCase {
static class Collaborator {
}
static class ClassUnderTest {
Collaborator getCollaborator() {
return new Collaborator();
}
}
#Tested
ClassUnderTest classUnderTest;
#Mocked
Collaborator collaborator;
#Test
public void test() {
new Expectations() {
{
new Collaborator();
result = ConstructorTest.this.collaborator;
}
};
Collaborator collaborator = this.classUnderTest.getCollaborator();
Assert.assertTrue("incorrect collaborator returned", collaborator == this.collaborator);
}
}
Any ideas on why this test fails and how to make it work would br greatly appreciated.
Thanks in advance,
Jim Renkel
Senior Technical Staff
mFluent, Inc. LLC
Change the #Mocked annotation to #Capturing, like this:
#Capturing
Collaborator collaborator;
This allows the test to pass for me.
This is a little bit of voodoo magic, in my opinion, but if you'd like to read more, take a look at Capturing internal instances of mocked types in the JMockit tutorial.
Also see Using JMockit to return actual instance from mocked constructor

Cant mock static functions with powermock-easymock-testng (non-maven project)

To tell you first, i have tried and tried it again and now i need some help
Heres my code
package staticPkg;
public class Static {
public static final String staticMethod() {
System.out.println("Static method called");
return "Static called";
}
}
package staticPkg;
public class TargetClass {
Static staticClass;
public String callHere() {
return Static.staticMethod();
}
}
package staticPkg;
import org.easymock.EasyMock;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
#PrepareForTest({Static.class})
public class TestClass {
Static staticClass = null;
#ObjectFactory
public IObjectFactory getObjectFactory() {
System.out.println("got object factory");
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
#BeforeMethod
public void setup() {
System.out.println("print me");
PowerMock.mockStatic(Static.class);
staticClass = PowerMock.createMock(Static.class);
}
#Test
public void testMe() {
EasyMock.expect(Static.staticMethod()).andReturn("Mock called").anyTimes();
PowerMock.replay(Static.class,staticClass);
TargetClass tc = new TargetClass();
String output = tc.callHere();
PowerMock.verify(Static.class,staticClass);
System.out.println(output);
}
}
And heres the log
[Parser] Running:
C:\MockWorkspace\Mock\temp-testng-customsuite.xml
got object factory
print me
Static method called
FAILED: testMe
java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
at org.easymock.EasyMock.expect(EasyMock.java:499)
at staticPkg.TestClass.testMe(TestClass.java:46)
... Removed 22 stack frames
===============================================
staticPkg.TestClass
Tests run: 1, Failures: 1, Skips: 0
===============================================
===============================================
Mock
Total tests run: 1, Failures: 1, Skips: 0
===============================================
Help please, i have tried a variety of solutions, can't get it done.
Please can anyone try this code and correct it for success?
I get error in EasyMock.expect ...............
Got a work around at http://blogs.bytecode.com.au/glen/2006/10/12/doing-bytecode-kungfu-with-javassist.html
And it works
But wait..........I am stuck again
My testcase works fine when runs alone, but when run with Ant, it gives problem. Might be other test cases of different files are interfering.
I got the same error, when my individual test case was using #PrepareTest & easymock/powermock
[testng] ====================STATIC CALLED===========================
[testng] javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClass
Loader): attempted duplicate class definition for name: "com/symantec/mobius/aggregator/submission/SubmissionFactory"
[testng] at javassist.ClassPool.toClass(ClassPool.java:1085)
[testng] at javassist.ClassPool.toClass(ClassPool.java:1028)
[testng] at javassist.ClassPool.toClass(ClassPool.java:986)
[testng] at javassist.CtClass.toClass(CtClass.java:1110)
Try extending from PowerMockTestCase. The TestNG support will also be updated in next version of PowerMock (1.4.9).
I faced this same issue, and struggled a lot. Finally, found the following solution:
Another alternative is to set the object-factory to org.powermock.modules.testng.PowerMockObjectFactory in the TestNG suite.xml. Here is a sample suite file:
<suite name="dgf" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
<test name="dgf">
<classes>
<class name="com.example.ClientTest"/>
</classes>
</test>
</suite>
Of course, you can also extend your test case from PowerMockTestCase as told by Johan.
Mock all the static methods in static class before proceeding to mock the static method. Try with this:
#Test
public void testMe() {
PowerMock.mockStatic(Static.class);
EasyMock.expect(Static.staticMethod()).andReturn("Mock called").anyTimes();
PowerMock.replay(Static.class,staticClass);
TargetClass tc = new TargetClass();
String output = tc.callHere();
PowerMock.verify(Static.class,staticClass);
System.out.println(output);
}