How to use ObjectifyService in Junit Testing - java

If you want to use datastore service to perform a junit test, this is what you do
LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalMemcacheServiceTestConfig(),new LocalDatastoreServiceTestConfig());
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
#Test
public void testInsert1() {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
assertEquals(0, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
ds.put(new Entity("yam"));
ds.put(new Entity("yam"));
assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
}
i have tried the above test using objectify
Public class myofyTest{
#Entity
private class Food{
#id Long id;
String foodtype;
public Food(String food){
foodtype = food ;
}
}
static{
ObjectifyService.register(Food.class);
}
LocalServiceTestHelper helper = new LocalServiceTestHelper
(new LocalMemcacheServiceTestConfig(),new LocalDatastoreServiceTestConfig());
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
#Test
public void testInsert1() {
Food food = new Food("yam");
ofy().save().entities(food).now();
}
}
but i get this kind of exception
java.util.ServiceConfigurationError: com.google.appengine.tools.development.
LocalRpcService: Provider com.google.appengine.api.datastore.dev.
LocalCloudDatastoreV1Service could not be instantiated
How do you implement this kind of test using ObectifyService instead of DatastoreService ?

You probably forgot to add required dependencies.
This is a working test for your question:
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.cache.AsyncCacheFilter;
import com.googlecode.objectify.util.Closeable;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static com.piyasatakip.backend.OfyService.ofy;
import static junit.framework.Assert.assertNotNull;
/**
* Created by devrimtuncer on 27/03/16.
*/
public class ObjectifyServiceTest {
private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
protected Closeable session;
#BeforeClass
public static void setUpBeforeClass() {
// Reset the Factory so that all translators work properly.
ObjectifyService.setFactory(new ObjectifyFactory());
ObjectifyService.register(Food.class);
}
#Before
public void setUp() {
this.session = ObjectifyService.begin();
this.helper.setUp();
}
#After
public void tearDown() {
AsyncCacheFilter.complete();
this.session.close();
this.helper.tearDown();
}
#Test
public void doTest() {
Food food = new Food("yam");
// 1) save food to data store
ofy().save().entity(food).now();
// 2) retrieve food from data store
Food foodRetrieved = ofy().load().type(Food.class).filter("foodtype", "yam").first().now();
assertNotNull(foodRetrieved);
}
#Entity
private class Food {
#Id
Long id;
#Index
String foodtype;
public Food(String food) {
foodtype = food;
}
}
}
Don't forget to add required dependencies.
i.e dependencies at build.gradle:
dependencies {
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.34'
compile 'com.google.appengine:appengine-endpoints:1.9.34'
compile 'com.google.appengine:appengine-endpoints-deps:1.9.34'
compile 'com.google.appengine:appengine-api-1.0-sdk:1.9.34'
compile 'com.googlecode.objectify:objectify:5.1.12'
compile 'javax.servlet:servlet-api:2.5'
compile 'org.jsoup:jsoup:1.7.2'
testCompile 'com.google.appengine:appengine-testing:1.9.34'
testCompile 'com.google.appengine:appengine-api-stubs:1.9.34'
testCompile 'junit:junit:4.4'
}

I noticed that you didn't have the following lines in your setup()
Closable session;
session = ObjectifyService.begin()
You will also need this before your helper.tearDown() in your tearDown():
session.close();

Related

Tests pass when test running individually but not pass when run the whole class

When i run test individually everythink is ok, but when i run the whole test class, i got this 3 exception in 3 method which i run, its: getPersonById / savePerson / deleteById . The remain method run success
getPersonById method:
java.util.NoSuchElementException: No value present
--
savePerson method:
javax.persistence.EntityNotFoundException: Unable to find
com.entity.Person with id 1
--
deleteById method:
org.springframework.dao.EmptyResultDataAccessException: No class
com.entity.Person entity with id 1 exists!
Code:
package com.repository;
import com.entity.Person;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
#DataJpaTest
class PersonRepositoryTest {
#Autowired
private PersonRepository personRepository;
private Person person;
#BeforeEach
public void setUp() {
person = new Person();
person.setId(1L);
person.setName("Test1");
person.setSurname("Test1_2");
person.setDate_of_birth("18 Years");
}
#AfterEach
void tearDown() {
personRepository.deleteAll();
}
#Test
public void shouldCheckIfPersonExists(){
personRepository.save(person);
assertTrue(personRepository.existsById(1L));
}
#Test
public void getAllPerson() {
personRepository.save(person);
List<Person> list = personRepository.findAll();
assertEquals(1, list.size());
}
#Test
public void getPersonById() {
personRepository.save(person);
Optional<Person> byId = personRepository.findById(1L);
assertEquals(person.getId(), byId.get().getId());
assertEquals(person.getName(), byId.get().getName());
}
#Test
public void savePerson() {
personRepository.save(person);
Person newPerson = personRepository.getById(1L);
assertEquals(person.toString(), newPerson.toString());
}
#Test
public void deleteById() {
personRepository.save(person);
personRepository.deleteById(1L);
assertFalse(personRepository.existsById(1L));
}
}
It probably fails because you use save() method which is not destined to save entities with ID set. This method automatically generates ID and that's why it's not always 1.

Mokito/Java - Static Methods Mock

For example I have the following classes below:
public class TesteEstatico {
public static String teste(){
return "FOO";
}
}
And I have a class that uses her method:
public class UsaTesteEstatico {
public String metodoParaTeste1 (){
return TesteEstatico.teste() + " BAR ";
}
public String metodoParaTeste2 (){
return "FOO "+TesteEstatico.teste() + " BAR ";
}
}
Test class:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class) public class UsaTesteEstaticoTest {
#InjectMocks
UsaTesteEstatico usaTesteEstatico;
#Test
void teste1(){
Mockito.mockStatic(TesteEstatico.class);
Mockito.when(TesteEstatico.teste())
.thenReturn("BANANA");
String res = usaTesteEstatico.metodoParaTeste1();
System.out.println(res);
}
#Test
void teste2(){
Mockito.mockStatic(TesteEstatico.class);
Mockito.when(TesteEstatico.teste())
.thenReturn("LARANJA");
String res = usaTesteEstatico.metodoParaTeste2();
System.out.println(res);
}
}
Error I get when trying to run the tests:
org.mockito.exceptions.base.MockitoException:
For TesteEstatico, static mocking is already registered in the current thread
To create a new mock, the existing static mock registration must be deregistered
Versions of the libs that are in the project:
junit-jupiter 5.5.2
mockito-junit-jupiter 3.2.14
mockito-inline 3.2.14
Any idea how to solve this, i've tried a few things but nothing successful.
NOTE: I cannot change or add any new libraries as it is a restricted project.
You should use try-with-resources block in each of the tests to close the mockStatic.
public class UsaTesteEstaticoTest {
UsaTesteEstatico usaTesteEstatico = new UsaTesteEstatico();
#Test
void teste1(){
try (var ms = Mockito.mockStatic(TesteEstatico.class)) {
Mockito.when(TesteEstatico.teste()).thenReturn("BANANA");
String res = usaTesteEstatico.metodoParaTeste1();
System.out.println(res);
}
}
#Test
void teste2(){
try (var ms = Mockito.mockStatic(TesteEstatico.class)) {
Mockito.when(TesteEstatico.teste()).thenReturn("LARANJA");
String res = usaTesteEstatico.metodoParaTeste2();
System.out.println(res);
}
}
}
Note on mockStatic in #BeforeAll
Using #BeforeAll is a trap and bad advice.
You should strive for independent tests that don't affect each other.
This is not the case for mockStatic called in #BeforeAll, as stubbing from test methods outlive the test methods.
For example
// BAD CODE DONT USE
public class UsaTesteEstaticoTest {
UsaTesteEstatico usaTesteEstatico = new UsaTesteEstatico();
static MockedStatic<TesteEstatico> ms;
#BeforeAll
public static void init() {
ms = Mockito.mockStatic(TesteEstatico.class);
}
#AfterAll
public static void close() {
ms.close();
}
#Test
void teste1() {
Mockito.when(TesteEstatico.teste()).thenReturn("BANANA");
String res = usaTesteEstatico.metodoParaTeste1();
System.out.println(res);
}
#Test
void teste2() {
String res = usaTesteEstatico.metodoParaTeste2();
System.out.println(res);
}
}
teste2 prints:
FOO BANANA BAR if run after teste1
FOO null BAR if run separately
This is precisely what you want to avoid.
you need to use static block to mock it.
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
public class UsaTesteEstaticoTest {
#InjectMocks
UsaTesteEstatico usaTesteEstatico;
#BeforeAll
public static void init(){
Mockito.mockStatic(TesteEstatico.class);
}
#Test
void teste1(){
Mockito.when(TesteEstatico.teste())
.thenReturn("BANANA");
String res = usaTesteEstatico.metodoParaTeste1();
System.out.println(res);
}
#Test
void teste2(){
Mockito.when(TesteEstatico.teste())
.thenReturn("LARANJA");
String res = usaTesteEstatico.metodoParaTeste2();
System.out.println(res);
}
}

How to create common object of a class to use in all methods Of TestNG class?

package com.test;
import org.testng.Reporter;
import org.testng.annotations.Test;
import org.openqa.selenium.support.PageFactory;
import utility.BaseClass;
import com.pages.LoginPageObjects;
public class UnderTest extends BaseClass
{
#Test(description = "Email login")
public void f()
{
Reporter.log("===dude===", true);
LoginPageObjects lpage = PageFactory.initElements(driver, LoginPageObjects.class);
lpage.click_signin_link();
lpage.enter_uid("test#gmail.com");
lpage.click_submit();
}
#Test(description = "fb login")
public void fe() throws InterruptedException
{
Reporter.log("===dude===", true);
LoginPageObjects lpage = PageFactory.initElements(driver, LoginPageObjects.class);
lpage.click_fb_button();
Thread.sleep(5000);
}
}
The test runs well if I create object separately in both the methods. When declared in #BeforeTest it is not working. How can I reduce the reuse of that statement?
In order to get access to LoginPageObjects instance, you have to create it as class variable. It will be accessible for all methods within your class.
Then, initialize this variable in #BeforeTest annotation.
public class UnderTest extends BaseClass {
private LoginPageObjects lpage;
#BeforeTest
public void setUp() throws Exception {
lpage = PageFactory.initElements(driver, LoginPageObjects.class);
}
#Test(description = "Email login")
public void f()
{
Reporter.log("===dude===", true);
lpage.click_signin_link();
lpage.enter_uid("test#gmail.com");
lpage.click_submit();
}
#Test(description = "fb login")
public void fe() throws InterruptedException
{
Reporter.log("===dude===", true);
lpage.click_fb_button();
Thread.sleep(5000);
}
Try the Following code...
package com.test;
import org.testng.Reporter;
import org.testng.annotations.Test;
import org.openqa.selenium.support.PageFactory;
import utility.BaseClass;
import com.pages.LoginPageObjects;
public class UnderTest extends BaseClass
{
#Before
public void setUp() throws Exception {
LoginPageObjects lpage = PageFactory.initElements(driver,
LoginPageObjects.class);
}
#Test(description = "Email login")
public void f()
{
Reporter.log("===dude===", true);
lpage.click_signin_link();
lpage.enter_uid("test#gmail.com");
lpage.click_submit();
}
#Test(description = "fb login")
public void fe() throws InterruptedException
{
Reporter.log("===dude===", true);
lpage.click_fb_button();
Thread.sleep(5000);
}
}

Datastore in GAE Testing environment leaks data between JUnit tests

I want to do some automated datastore tests for the Google App Engine locally with Junit.
I have written a class 'Agent.java' with three Strings 'name', 'owner' and 'url'. The class 'Player' is abstract, but does not provide additional attributes.
public class Agent extends Player implements Serializable {
/** to serialize Agent */
private static final long serialVersionUID = -6859912740484191335L;
/** The name of the Agent is the key-element of the agent-class*/
#Id String name;
/** Url to the Agent */
String url;
#Index String owner;
...
Followed by Setters and Getters.
I have copied the 4 needed library from the sdk 1.6.0 to the projects 'war/WEB-INF/lib' folder and included the Junit4 Container.
My test class looks like this:
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Logger;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.code.twig.annotation.AnnotationObjectDatastore;
public class AgentContrTest {
private static final Logger log = Logger.getLogger("AgentContrTest.class");
private static UserController uc;
private static GameController gc;
private static AgentController ac;
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
private AnnotationObjectDatastore datastore = new AnnotationObjectDatastore(false);
#BeforeClass
public static void setUpOnce() {
gc = GameController.getInstance();
uc = UserController.getInstance();
ac = AgentController.getInstance();
}
#Before
public void setUp() {
helper.setUp();
try {
uc.register("userForTest", "test", "test#gmail.de", false);
}
catch (NameExistsException ne) {
}
catch (EmailFormatException ee) {
}
}
#After
public void tearDown() {
helper.tearDown();
}
// Testing the raising of NameExistsException in createAgent(String name, String url, String owner)
#Test(expected=NameExistsException.class)
public void testCreateAgentExc1() throws NameExistsException {
Agent ag1 = ac.createAgent("Agent1", "www.agent1.com", "Owner1");
Agent ag2 = ac.createAgent("Agent1", "www.agent2.com", "Owner2");
}
// Testing getAgents()
#Test
public void testGetAgents1() throws NameExistsException {
datastore.disassociateAll();
ArrayList<Agent> agents1 = ac.getAgents();
ac.createAgent("Agent1", "www.agent1.com", "Owner1");
ac.createAgent("Agent2", "www.agent2.com", "Owner2");
ac.createAgent("Agent3", "www.agent3.com", "userForTest");
ArrayList<Agent> agents2 = ac.getAgents();
assertTrue(agents1.size()==0);
assertTrue(agents2.size()==3);
datastore.disassociateAll();
}
// Testing getAgents(String user)
#Test
public void testGetAgents2() throws NameExistsException {
ArrayList<Agent> agents = ac.getAgents();
assertTrue(agents.size()==0);
datastore.disassociateAll();
ac.createAgent("Agent1", "www.agent1.com", "Owner1");
ac.createAgent("Agent2", "www.agent2.com", "Owner2");
ac.createAgent("Agent3", "www.agent3.com", "userForTest");
ArrayList<Agent> agents2 = ac.getAgents("userForTest");
assertTrue(agents2.size()==1);
}
These are the functions in my AgentController that I am testing:
public ArrayList<Agent> getAgents(String user) {
ArrayList<Agent> agents = new ArrayList<Agent>();
Iterator<Agent> agentIterator = datastore.find().type(Agent.class)
.addFilter("owner", FilterOperator.EQUAL, user)
.now();
while (agentIterator.hasNext()) {
agents.add(agentIterator.next());
}
return agents;
}
public Agent createAgent(String name, String url, String owner) throws NameExistsException {
Agent agent = datastore.load(Agent.class, name);
if (agent != null)
throw new NameExistsException();
agent = new Agent();
agent.setName(name);
agent.setUrl(url);
agent.setOwner(owner);
datastore.store(agent);
return agent;
}
The testCreateAgentExc1 is working just fine. But the testGetAgents2() is throwing a NameExistsException, which it should not do. If i rename the agents in this test to 'Agent4' to 'Agent6' it is working just fine.
Due to 'http://code.google.com/intl/de-DE/appengine/docs/java/tools/localunittesting.html'
the Datastore should delete all data between the tests, so the NameExistsException should not be raised.
You are not resetting your datastore object between tests. I'm not sure how twig works, but it (or its configuration) is the cause of the leak.
I don't have experience in testing GAE, but there's one difference between your code and the code on Google's page.
You're using a class variable
private static final LocalServiceTestHelper helper
= new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
whereas Google uses a field
private final LocalServiceTestHelper helper
= new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

Detect Failure or Error of Junit Test in #After method

Is there a way in JUnit to detect within an #After annotated method if there was a test failure or error in the test case?
One ugly solution would be something like that:
boolean withoutFailure = false;
#Test
void test() {
...
asserts...
withoutFailure = true;
}
#After
public void tearDown() {
if(!withoutFailuere) {
this.dontReuseTestenvironmentForNextTest();
}
}
This is ugly because one need to take care of the "infrastructure" (withoutFailure flag) in the test code.
I hope that there is something where I can get the test status in the #After method!?
If you are lucky enough to be using JUnit 4.9 or later, TestWatcher will do exactly what you want.
Share and Enjoy!
I extend dsaff's answer to solve the problem that a TestRule can not execute some code snipped between the execution of the test-method and the after-method. So with a simple MethodRule one can not use this rule to provide a success flag that is use in the #After annotated methods.
My idea is a hack! Anyway, it is to use a TestRule (extends TestWatcher). A TestRule will get knowledge about failed or success of a test. My TestRule will then scan the class for all Methods annotated with my new AfterHack annotations and invoke that methods with a success flag.
AfterHack annotation
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target(METHOD)
public #interface AfterHack {}
AfterHackRule
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
public class AfterHackRule extends TestWatcher {
private Object testClassInstance;
public AfterHackRule(final Object testClassInstance) {
this.testClassInstance = testClassInstance;
}
protected void succeeded(Description description) {
invokeAfterHackMethods(true);
}
protected void failed(Throwable e, Description description) {
invokeAfterHackMethods(false);
}
public void invokeAfterHackMethods(boolean successFlag) {
for (Method afterHackMethod :
this.getAfterHackMethods(this.testClassInstance.getClass())) {
try {
afterHackMethod.invoke(this.testClassInstance, successFlag);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
throw new RuntimeException("error while invoking afterHackMethod "
+ afterHackMethod);
}
}
}
private List<Method> getAfterHackMethods(Class<?> testClass) {
List<Method> results = new ArrayList<>();
for (Method method : testClass.getMethods()) {
if (method.isAnnotationPresent(AfterHack.class)) {
results.add(method);
}
}
return results;
}
}
Usage:
public class DemoTest {
#Rule
public AfterHackRule afterHackRule = new AfterHackRule(this);
#AfterHack
public void after(boolean success) {
System.out.println("afterHack:" + success);
}
#Test
public void demofails() {
Assert.fail();
}
#Test
public void demoSucceeds() {}
}
BTW:
1) Hopefully there is a better solution in Junit5
2) The better way is to use the TestWatcher Rule instead of the #Before and #After Method at all (that is the way I read dsaff's answer)
#see
I don't know any easy or elegant way to detect the failure of a Junit test in an #After method.
If it is possible to use a TestRule instead of an #After method, one possibility to do it is using two chained TestRules, using a TestWatcher as the inner rule.
Example:
package org.example;
import static org.junit.Assert.fail;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
public class ExampleTest {
private String name = "";
private boolean failed;
#Rule
public TestRule afterWithFailedInformation = RuleChain
.outerRule(new ExternalResource(){
#Override
protected void after() {
System.out.println("Test "+name+" "+(failed?"failed":"finished")+".");
}
})
.around(new TestWatcher(){
#Override
protected void finished(Description description) {
name = description.getDisplayName();
}
#Override
protected void failed(Throwable e, Description description) {
failed = true;
}
})
;
#Test
public void testSomething(){
fail();
}
#Test
public void testSomethingElse(){
}
}

Categories