how to do junit test for data base insertion using hibernate - java

I was trying to do j-unit test for project which insert values into database using hibernate classes. The program is creating tables and inserting values into database. but i am not able to do the j-unit part for the test?
I have attached the java table, but the value that i inserting using the test file is not display when i debugged it?
Sample.java
#Entity
public class Sample {
#Id
private int sid;
private String name;
public void set_sid(int sid)
{
this.sid=sid;
}
public void set_name(String name)
{
this.name=name;
}
public int get_sid()
{
return sid;
}
public String get_name()
{
return name;
}
}
SampleInsert.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleInsert {
private Sample s;
private static SessionFactory sf;
public void insert() {
sf = new Configuration().configure(new File("C:/Users/ns068002/eclipse-workspace/JAXRS-HelloWorld1/src/main/java/com/javacodegeeks/enterprise/rest/jersey/hibernate.cfg.xml")).buildSessionFactory();
Session session = sf.getCurrentSession();
session.beginTransaction();
Sample s=(Sample) session.get(Sample.class, 1);
System.out.println(s+"2");
System.out.println(s.get_name());
session.getTransaction().commit();
}
}
SampleInsertTest.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleTest {
Session session;
SampleInsert st;
#Before
public void setUp() {
session=mock(Session.class);
st=new SampleInsert();
}
#Test
public void test() {
Sample s=new Sample();
s.set_sid(1);
s.set_name("gopal");
Mockito.when(session.get(Sample.class,1)).thenReturn(s);
System.out.println(s+"1");
st.insert();
}
}

Looking at your code, I can not see how you would be able to mock/stub the Session or SessionFactory as neither of these things are "injected" into the class SampleInsert.
By "injected" I mean that the values are not passed into the class in some way, this is usually done using annotation with a framework like Spring, or via constructors.
It should be remembered that we are not testing the thing we are mocking, we are replacing the thing being mocked with a representation that is much simpler in order to test a component that makes use of the thing being mocked.
As an example of how you might use Mockito:
public interface SomethingToMock {
int returnSomeValueFor(int value);
}
public class ToBeTested {
private SomethingToMock session;
public ToBeTested(SomethingToMock session) {
this.session = session;
}
public void methodToTestA(int value) {
returnSomeValueFor(value);
}
public int methodToTestB(int value) {
int i = returnSomeValueFor(value);
return i * i;
}
}
#RunWith(MockitoJUnitRunner.class)
public class SomeTests {
#Mock
private SomethingToMock aMock;
private ToBeTested underTest;
#Before
public void setUp() {
underTest = new ToBeTested(aMock);
}
#Test
public void testOne() {
underTest.MethodToTestA(3);
verify(aMock).returnSomeValueFor(3);
}
#Test
public void testTwo() {
when(aMock.returnSomeValueFor(3)).thenReturn(2);
int r = underTest.methodToTestB(3);
assertEqual(r, 4);
}
}
In the example above we create an interface, this represents the thing to be mocked, we should aim to only mock interfaces and only those we or our team has created.
We then have a class that we need to test that uses the interface ToBeTested we can assume that concrete implementation of the interface are tested elsewhere in the project.
ToBeTested has two methods to test, one that has no return so has no side effects that we can see. The second method does some processing and has a side effect.
We then create a test class to test both methods, we insure it is setup to use Mockito (#RunWith(MockitoJUnitRunner.class) we then setup a mock using #Mock, the final setup step is to ensure our class has the mock "injected" into it, this is done in the setUp() method.
Finally we create two tests the first verifies that the mocked method is called, we don't have to set up a when for this in this case as no value will be returned from the method we are testing, just from the method being mocked I believe Mockito will return the default for an int.
The second test tests that a value is returned, thus we setup a when, when the mocked method is called in the way specified in the when the given value is returned and we can assert that the correct value is returned from the method under test, in this case using assertThat
This is the general layout of testing with Mockito. Effective testing is a huge topic, I would suggest you do some research on the web. The Mockito and JUnit docs are very good, and of course GitHub has many projects using both; one idea might be to look at the Mockito and Unit on Github and look at their testing.
Also the Mockito documentation does a very good job of explaining how, why and when to use mocking: http://static.javadoc.io/org.mockito/mockito-core/2.25.1/org/mockito/Mockito.html
I hope this helps.

Related

Mockito when not resetting between Tests [duplicate]

I am seeing behaviour that I believe is a bug. #InjectMocks does not seem to create a new test subject before every test method. Where as #Mock does. In the following example, if Subject.section is final one #Test fails. If its not final both pass. My current workaround is to use #BeforeClass, but this is not ideal.
Subject.java:
package inject_mocks_test;
public class Subject {
private final Section section;
public Subject(Section section) {
this.section = section;
}
public Section getSection() {
return section;
}
}
Section.java:
package inject_mocks_test;
public class Section {}
SubjectTest.java
package inject_mocks_test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class SubjectTest {
#Mock
Section section;
#InjectMocks
Subject subject;
#BeforeMethod
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1() {
assertEquals(section, subject.getSection());
}
#Test
public void test2() {
assertEquals(section, subject.getSection());
}
}
Cheers.
You are using the #InjectMocks for constructor incjection. This will work as long as Mockito finds the field not initalized (null). JUnit is creating a new instance of the test class before each test, so JUnit fans (like me) will never face such problem. TestNg is not creating a new instance of test class. It's keeping the state between test methods, so when MockitoAnnotations.initMocks(this) is called for the second time, Mockito will find subject field already initialized and will try to use field injection. This on the other turn will work until the field is not final.
Is this is a bug? I believe not - rather a natural consequence of the API design.
Some workaround for you would be to add
this.subject = null;
in some #AfterMethod method.

Injecting beans in a JUnit/Mockito test returns zero

I have a JavaEE application with Stateless EJBs that I use for business logic (EjbBusiness) and database access (EjbDAO). I need to run a unit test on EjbBusiness, but the DAO method always returns zero.
In the example below I have both classes and the unit test. I mock the EjbDAO method that connects to the database, to return a testing SQL connection:
#Stateless
public class EjbDAO {
public Connection getConnFromPool() {
Connection conn = null; // in production this would return a connection
return conn;
}
public int add2(int i) {
Connection conn = getConnFromPool();
System.out.println("in EjbDAO: " + i);
return i + 2;
}
}
#Stateless
public class EjbBusiness {
#Inject
private EjbDAO dao;
public int add2(int i) {
int j = dao.add2(i);
System.out.println("in EjbBusiness: " + j);
return j;
}
}
Since I mock one of the methods of EjbDAO, I annotate it with #Spy in UnitTest:
#RunWith(MockitoJUnitRunner.class)
public class UnitTest {
#InjectMocks
private EjbBusiness biz;
#InjectMocks
#Spy
private EjbDAO dao;
#Before
public void setup() {
dao = Mockito.mock(EjbDAO.class);
biz = Mockito.mock(EjbBusiness.class);
MockitoAnnotations.initMocks(this);
}
#Test
public void testBean() {
// this would return the testing connection
Mockito.doReturn(null).when(dao).getConnFromPool();
int i = biz.add2(3);
assertThat(5).isEqualTo(i);
}
}
Problem is that the assertion doesn't work, as biz.add2(3) returns zero instead of 5. Also, the System.out.println in both beans is not printed. How to declare/mock the beans for the test to work?
Use #InjectMocks only when you calling actual method otherwise don't use it. And also don't use #InjectMocks and Mockito.mock() or #Mock together.
In your code you are using #InjectMocks on dao object and you are also creatign mock for that. And use Mockito.mock() when you want to stub the method calls instead of calling actual methods.
System.out.println() is not working in your code because you created mocks for objects biz and dao. Actual methods (i.e add2() because of this you are getting 0 as output) not executed when you call with mock objects.
For more info on when to use #InjectMocks refer
this
#RunWith(MockitoJUnitRunner.class)
public class UnitTest {
#InjectMocks
private EjbBusiness biz;
#Mock
private EjbDAO dao;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testBean() {
// this would return the testing connection
Mockito.doReturn(null).when(dao).getConnFromPool();
Mockito.doCallRealMethod().when(dao).add2(Mockito.anyInt());
int i = biz.add2(3);
assertThat(i).isEqualTo(5);
}
}
You should not use one unit test to test both classes.
You should have two test classes to test them.
For Example,
#RunWith(MockitoJUnitRunner.class)
public class EjbBusinessTest {
#InjectMocks
private EjbBusiness biz;
#Mock
private EjbDAO dao;
#Test
public void testAdd2() {
// this would return the testing connection
Mockito.doReturn(null).when(dao).getConnFromPool();
Mockito.doReturn(5).when(dao).add2();
int i = biz.add2(3);
assertThat(5).isEqualTo(i);
}
}
In the above class we are testing only the method EjbBusinessTest.add2 and we don't care what happens or if the method EjbDAO.add2 is working properly. In this all we should care is whether the method under test is working properly, hence we mock everything external to that method.
Following a similar approach for EjbDAO.add2 as well, The test case should look like something given below. I have also made the method EjbDAO.getConnection private so that that should also be included in the test. This choice should be made by you if you need to make it private or public. If you decide to keep it public then you should use #Spy on EjbDAO and mock the EjbDAO.getConnection method.
#RunWith(MockitoJUnitRunner.class)
public class EjbDAOTest {
//instantiate this object the way you want. Mock the external objects used inside this like the library used to get connection inside EjbDAO.getConnection() Method
#InjectMocks
private EjbDAO dao;
#Test
public void testAdd2() {
// I would suggest you to make the getConnection method private.
// do not mock the getConnection here, instead mock how you are getting the connection inside the getConnection method.
int i = dao.add2(3);
assertThat(5).isEqualTo(i);
}
}
Hope it helps.

How to write non-encapsulated unit tests?

I have an autowired variable
#Autowired
private DocumentConfig documentConfig;
I want to make tests for the DocumentService with various states of this configuration object. What are my options? What is the best option?
The first idea is this:
#Test
public void save_failure() {
documentConfig.setNameRequired(true);
/*
testing code goes here
*/
documentConfig.setNameRequired(false);
}
But I want to be somewhat more sure that the variable is reset after the test to not interfere with the other tests, to make sure only this test gets an error if it's the source of a problem.
My new idea was this:
#Before
public void after() { documentConfig.setNameRequired(true); }
#Test
public void save_failure() {
/*
testing code goes here
*/
}
#After
public void after() { documentConfig.setNameRequired(false); }
However, this doesn't work at all because Before and After execute for the whole file and not this single test. I would prefer not to make a new file just for one test.
I've now settled on a compromise:
#Test
public void save_failure() {
documentConfig.setNameRequired(true);
/*
testing code goes here
*/
}
#After
public void after() { documentConfig.setNameRequired(false); }
It seems to do everything I want but I have a few questions.
Assuming nameRequired starts as false, is this guaranteed not to interfere with the other tests?
Is there any way I can make this more clear? Both for my future self and for others.
You can create it before each test. Smth like
private DocumentConfig documentConfig;
#Before
public void createConfig() {
documentConfig = new DocumentConfig(mockedParams);
}
An often used approach is to set up a dummy DocumentConfig and inject it within the setUp() method (annotated with #Before) so that the entire context is reset within each test, for example:
#Before
public void setUp() {
this.documentConfig = new DocumentConfig();
this.documentConfig.setNameRequired(false);
this.service = new DocumentService(this.documentConfig);
}
In this case, I've set up a simple object with nameRequired being false. I could probably delete that statement, because a boolean field defaults to false anyways.
If you don't use constructor injection, and you don't have a setter for documentConfig, you'll have to use reflection to inject the field, for example:
ReflectionTestUtils.setField(this.service, "documentConfig", this.documentConfig);
Within your test you could now write something like this:
#Test
public void save_failure() {
this.documentConfig.setNameRequired(true);
// TODO: Implement test
}
Alternatively, you could mock DocumentConfig, so that you don't rely on its implementation to test DocumentService. I assume that you're calling isNameRequired() somewhere in the code of DocumentService, so you could mock it like this:
#Before
public void setUp() {
// Use a static import for Mockito.mock()
this.documentConfig = mock(DocumentConfig.class);
this.service = new DocumentService(this.documentConfig);
}
#Test
public void save_failure() {
// Use a static import for Mockito.when()
when(this.documentConfig.isNameRequired()).thenReturn(true);
// TODO: Implement test
}
Since this mocking/injection setup happens quite often, Mockito also has its own runner that allows you to get rid of the setUp() method, for example:
#RunWith(MockitoJUnitRunner.class)
public class DocumentServiceTest {
#InjectMocks
private DocumentService documentService;
#Mock
private DocumentConfig documentConfig;
#Test
public void save_failure() {
when(this.documentConfig.isNameRequired()).thenReturn(true);
// TODO: Implement test
}
}
It is not yet clear, which testing framework you use. For plain unit tests, make the value injectable by either a setter or constructor injection. Whatever suits your specific situation best.
If there's a lot (more than three ;-) ) of such values to be injected, you may consider introducing a configuration class to inject all those values as a single parameter.

Best practice - Setting a field without setters in a unit test

Let's say you have the following class you would like to test:
public class SomeService {
public String someMethod(SomeEntity someEntity) {
return someEntity.getSomeProperty();
}
}
The SomeEntity looks like this:
public class SomeEntity {
private String someProperty;
public getSomeProperty() {
return this.someProperty;
}
}
The assertion you would like to do can be the following:
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
How can you make this test work?
1) Add a setter for 'someProperty' in the SomeEntity class. I don't think this a good solution because you don't change production code to make your tests work.
2) Use ReflectionUtils to set the value of this field. Test would look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntity someEntity = new SomeEntity();
ReflectionTestUtils.setField(someEntity, "someProperty", "someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
}
3) You create an inner class in your test class that extends the SomeEntity class and adds the setter for this field. However, for this to work you will also need to change the SomeEntity class because the field should become 'protected' instead of 'private'. Test class might look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntityWithSetters someEntity = new SomeEntityTestWithSetters();
someEntity.setSomeProperty("someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
public class SomeEntityWithSetters extends SomeEntity {
public setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
}
}
4) You use Mockito to mock SomeEntity. Seems fine if you only need to mock only one property in the class, but what if you need to mock like 10 properties are so. The test might look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntity someEntity = mock(SomeEntity.class);
when(someEntity.getSomeProperty()).thenReturn("someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
}
you can set the value using reflection. It doesn't need any change in production code.
ReflectionTestUtils.setField(YourClass.class, "fieldName", fieldValue);
You can add a setter with default (package private) scope.
With junit testing of SomeService.someMethod()
alternative 1. should not use this as no need to change entity for writing junit.
alternative 2. can be used.
alternative 3. again same a 3, no need to extend for just junit. how about when the class cannot be extended.
alternative 4. yes, a good option. mockito is being used for the same reason.
What is the behavior / contract specific to SomeService that is testable? Based upon your skeletal code, there really isn't any. It will either throw a NPE on bad input, or return a String that may or may not be null, depending on Hibernate magic. Not sure what you can actually test.
I have been through this same dilemma many times before, a quick solution is to make the field you want to mock package protected, or provide a protected setter. Of course both will alter production code.
Alternatively, you can consider dependency injection framework, such as Dagger. Below is an example they give:
#Module
class DripCoffeeModule {
#Provides Heater provideHeater(Executor executor) {
return new CpuHeater(executor);
}
}
This JUnit test overrides DripCoffeeModule's binding for Heater with a mock object from Mockito. The mock gets injected into the CoffeeMaker and also into the test.
public class CoffeeMakerTest {
#Inject CoffeeMaker coffeeMaker;
#Inject Heater heater;
#Before public void setUp() {
ObjectGraph.create(new TestModule()).inject(this);
}
#Module(
includes = DripCoffeeModule.class,
injects = CoffeeMakerTest.class,
overrides = true
)
static class TestModule {
#Provides #Singleton Heater provideHeater() {
return Mockito.mock(Heater.class);
}
}
#Test public void testHeaterIsTurnedOnAndThenOff() {
Mockito.when(heater.isHot()).thenReturn(true);
coffeeMaker.brew();
Mockito.verify(heater, Mockito.times(1)).on();
Mockito.verify(heater, Mockito.times(1)).off();
}
}

Test class should have exactly one public zero-argument constructor

I have written a test class, such that is following
public class MyParameterizedClassTest extends BaseRepositoryTest {
private int multiplierA;
private int multiplierB;
public MyParameterizedClassTest(int multiplierA) {
this.multiplierA = multiplierA;
}
#Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] { { 1 }, { 5 }, { 121 } };
return Arrays.asList(data);
}
#Test
public void testMultiplyException() {
assertEquals("Result", multiplierA * multiplierA,multiply(multiplierA));
}
public int multiply(int a){
return a*a;
}
}
And My BaseRepositoryTest class is following
#RunWith (Parameterized.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public abstract class BaseRepositoryTest extends
AbstractJUnit4SpringContextTests {
#Inject
SessionFactory sessionFactory;
private Transaction transaction;
public Session getSession() {
Session session;
try {
session = sessionFactory.getCurrentSession();
} catch (SessionException se) {
session = sessionFactory.openSession();
}
return session;
}
#Before
public void setUp() throws Exception {
transaction = getSession().beginTransaction();
}
#After
public void tearDown() throws Exception {
if (transaction != null) {
transaction.rollback();
}
getSession().close();
}
#Before
public void baseSetUp() {
MockitoAnnotations.initMocks(this);
}
}
When I run my test class it shows like,
Test class should have exactly one public zero-argument constructor:at
org.junit.runners.BlockJUnit4ClassRunner.validateZeroArgConstructor
I want to make a test method with #parameters,so please Can anyone please help to find the solution
JUnit 4 vs 5 (Jupiter)
I had this issue when I imported the wrong Test class. While a constructor was using JUnit 5 features, I imported the old org.junit.Test rather than org.junit.jupiter.api.Test.
I think the problem is that you defined two test runners. One by yourself #RunWith (Parameterized. class) and one that comes with spring, because an AbstractJUnit4SpringContextTests defines a #RunWith(SpringJUnit4ClassRunner.class).
Since Junit can only deal with one #RunWith you can only use #Parameterized or AbstractJUnit4SpringContextTests. If you want to use both you have to use #Parameterized and than do the same logic that a SpringJUnit4ClassRunner does on your own.
A simple approach can be to just use spring's org.springframework.test.context.TestContextManager.
#RunWith(Parameterized.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public abstract class BaseRepositoryTest extends AbstractJUnit4SpringContextTests {
private TestContextManager testContextManager;
#Before
public void setUpContext() throws Exception {
this.testContextManager = new TestContextManager(getClass());
this.testContextManager.prepareTestInstance(this);
}
}
But this only ensures that the TestExecutionListeners are invoked. Spring normally does a lot more like application context caching and so on. Also a tear down method should be implemented that closes the application context.
If you're running a single test, make sure that you wrote your test class name correctly
A common mistake that I do is to have a class named 'Foo' and a test class named
'FooTest'
and run a single unit test with
'Foo'
instead of 'FooTest'
If 'Foo' has a public constructor with arguments I get the error:
java.lang.Exception: Test class should have exactly one public zero-argument constructor
This error is thrown when your class is not defined as public
In your case it is abstract, so it can not be instantiate for testing propouses
Try removing constructor from MyParameterizedClassTest class.
I was getting this error when my test class had a public constructor. After removing, it started working.
I have got one answer,it fix on my machine
JUnit4 -> when u check the exception
org.junit.runners.BlockJUnit4ClassRunner.validateZeroArgConstructor(BlockJUnit4ClassRunner.java:171)
org.junit.runners.BlockJUnit4ClassRunner.validateConstructor(BlockJUnit4ClassRunner.java:148)
get inside to first exception
protected void validateZeroArgConstructor(List<Throwable> errors) {
if(!this.getTestClass().isANonStaticInnerClass() && this.hasOneConstructor() && this.getTestClass().getOnlyConstructor().getParameterTypes().length != 0) {
String gripe = "Test class should have exactly one public zero-argument constructor";
errors.add(new Exception(gripe));
}
}
it will check your constructor is none-parameters or not
Try setter injection or field(->field is not recommended officially)

Categories