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!
Related
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.
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.
I am trying to add JUnit tests to a Tomee web-application that uses CDI and JPA. Leaving out the different hurdles of the last two weeks (including very intensive research on stackoverflow as well as other sources), my problem appears to be quite concrete:
Running the unit test gives this error message:
org.apache.openejb.Injector$NoInjectionMetaDataException:
org.demo.service.GenericServiceTest : Annotate the class with #javax.annotation.ManagedBean so it can be discovered in the application scanning process
at org.apache.openejb.Injector.inject(Injector.java:54)
at org.apache.openejb.OpenEjbContainer$GlobalContext.bind(OpenEjbContainer.java:656)
...
This I don't understand, for I have annotated the class just as required. Any idea what I can do to resolve this?
(Or does the error refer to the injected class - GenericService? I cannot annotate this #ManagedBean, for it is already #Stateless).
Here are some details of my project:
gradle dependencies:
dependencies {
compile 'org.apache.commons:commons-lang3:3.3.2'
compile "com.googlecode.json-simple:json-simple:1.1.1"
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.8.6'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.6'
compile 'log4j:log4j:1.2.16'
testCompile "org.apache.openejb:tomee-embedded:1.7.3"
compile "javax:javaee-api:7.0"
compile 'mysql:mysql-connector-java:5.1.16'
}
(I have put the testCompile inbetween, because there is a ticket stating the importance of the order: EJB testing with TomEE embedded EJBContainer api: java.lang.ClassFormatError exception)
My Test class is this:
package org.demo.service;
import java.io.File;
import java.util.Properties;
import javax.annotation.ManagedBean;
import javax.ejb.embeddable.EJBContainer;
import javax.inject.Inject;
import javax.naming.NamingException;
import org.apache.openejb.OpenEjbContainer;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
#ManagedBean
public class GenericServiceTest {
private static EJBContainer ejbContainer;
#Inject
private GenericService service;
#Test
public void test() throws NamingException {
System.out.println("service: " + service);
}
#BeforeClass
public static void start() {
Properties p = new Properties();
try {
p.put(EJBContainer.MODULES, new File("bin"));
} catch (Exception e1) {
e1.printStackTrace();
}
p.put(OpenEjbContainer.Provider.OPENEJB_ADDITIONNAL_CALLERS_KEY, GenericService.class.getName());
ejbContainer = javax.ejb.embeddable.EJBContainer.createEJBContainer(p);
}
#Before
public void inject() throws NamingException {
ejbContainer.getContext().bind("inject", this);
}
#AfterClass
public static void shutdownContainer() {
if (ejbContainer != null) {
ejbContainer.close();
}
}
}
Maybe I'm running totally in the wrong direction here - Please let me know if I should choose a different approach - All I want is to add unit tests to my web application (preferably without introducing Weld/JBoss or other implementations as alternatives to the implementations I already use in the application itself).
Thank you very much in advance!
I would recommand you to read http://tomee.apache.org/developer/testing/index.html , there are some examples
Regarding your test it uses openejb embedded and not tomee embedded and deploys bin/ as an application. the hack bind("inject") only works with classpath deployment (no module).
I am developing a light weight server App with a RESTful api implemented with Jersey 2.12 and Jackson 2.
I am writing tests while developing using JUnit and JerseyTest. I know that my Jersey Resources work as expected including the marshalling from and to JSON because I tested them manually with the PostMan Chrome plugin.
My GET tests with query parameters work well too, based on the example in the Jersey documentation
Here is a simplified (I have left out boilerplate code to make the idea clearer) example of a test I'd like to write:
import static org.junit.Assert.assertTrue;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import com.acme.api.rest.SessionsEndPoint;
import com.acme.api.rest.beans.UserCredentialsBean;
public class TestSession extends JerseyTest {
#Override
protected Application configure() {
return new ResourceConfig(SessionsEndPoint.class);
}
#Test
public void test() {
UserCredentialsBean userCredentialsBean = new UserCredentialsBean();
userCredentialsBean.setUserId("alice");
userCredentialsBean.setPassword("secret");
WebTarget theTarget = target("sessions/login");
Response response = theTarget.request().post( Entity.entity(UserCredentialsBean.class, "application/json"));
assertTrue(true);
}
}
The basic problem I have is that I cannot find any documentation on how to properly use the WebTarget class for post requests. the WebTarget theTarget is constructed correctly but the line:
Response response = theTarget.request().post( Entity.entity(UserCredentialsBean.class, "application/json"));
does not work.
As I understand the WebTarget class is fairly new in the JerseyTest framework. Is there anybody who can point me at any recent documentation, examples, or just explain here how I can get this to work?
I did do a lot of googling before I posted my question here, but after checking back my eyes suddenly fell on this Related Question. I did search on SO several times but never found this question. Anyway, here's the solution to my problem:
I started implementing as explained in the accepted answer and got it to work quickly.
Then I decided that you it should be possible to avoid using JSON string representations at all, and I got that to work to.
The code above works if modified as follows:
import static org.junit.Assert.assertTrue;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import com.acme.api.rest.SessionsEndPoint;
import com.acme.api.rest.beans.UserCredentialsBean;
public class TestSession extends JerseyTest {
#Override
protected Application configure() {
return new ResourceConfig(SessionsEndPoint.class);
}
#Test
public void test() {
UserCredentialsBean userCredentialsBean = new UserCredentialsBean();
userCredentialsBean.setUserId("alice");
userCredentialsBean.setPassword("secret");
LoginResponseBean loginResponseBean =
target("sessions/login")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(
Entity.entity(
userCredentialsBean,
MediaType.APPLICATION_JSON_TYPE
),
LoginResponseBean.class
);
assertTrue(
loginResponseBean.isSuccess()
&&
loginResponseBean.getToken().length()==36
);
}
}
LoginResponseBean is a plain Java Bean. Just getters and setters and a default constructor.
Marshalling to- and from JSON is done by the framework, either by moxy or jackson as the JSON provider.
My source code like below.
It has a error, "No exception of type DataAccessException can be thrown; an exception type must be a subclass of Throwable".
I can't understand why the error ocurrs.
let me know. thx.
package com.sds.afi.cosmos.cmm.db.impl;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.stereotype.Repository;
import com.sds.afi.cosmos.cmm.db.MainDao;
#Repository
//#SuppressWarnings("unchecked") // 부적절한 컴파일러의 경고를 제거
public class MainDaoImpl extends SqlMapClientDaoSupport implements MainDao {
#Autowired
private SqlMapClientTemplate sqlMapClientTemplate;
#SuppressWarnings("unchecked")
#Override
public List<HashMap> getUserInfo() throws DataAccessException {
List<HashMap> lists;
lists = sqlMapClientTemplate.queryForList("common.getList");
return lists;
}
}
This can happen if some class in the type-hierarchy of the exception is not on the class-path. In that case, its not possible to verify whether the exception really extends Throwable, whether it is a checked one or not, etc. Hence the errors. e.g superclass of Dataaccessexception : NestedRuntimeException may be missing from the class-path as it is in a differnt jar i.e. spring-core.
Your DataAccessException is not a subclass of Throwable class (extends Throwable). It should be, and without this inheritance, your code is not compilable with the current throws clause.
Here is an example: http://www.osix.net/modules/article/?id=754
I had this same issue when I upgraded to 5.X.X version. I have added Spring-core.jar file and it worked fine for me. Just adding this here because it may help some one. Spring txn jar , dao jar and spring core are must.
This means that in your getUserInfo() method there is no code that throws that exception. So just remove the throws clause from your method declaration.
I was facing same problem.
What I have done wrong was I have created Exception class(by mistake) of my own.
In other programs I was trying to extend Exception class(default) but complier(eclipse)was loading user defined Exception class giving me same error.
So please make sure you are not overriding any default class.