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());
Related
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);
}
}
I want to mock a private method which has been called inside another method.
Following is the sample code, I have written.
Java code:
package org.mockprivatemethods;
public class AccountDeposit {
// Instantiation of AccountDetails using some DI
AccountDetails accountDetails;
public long deposit(long accountNum, long amountDeposited){
long amount = 0;
try{
amount = accountDetails.getAmount(accountNum);
updateAccount(accountNum, amountDeposited);
amount= amount + amountDeposited;
} catch(Exception e){
// log exception
}
return amount;
}
private void updateAccount(long accountNum, long amountDeposited) throws Exception {
// some database operation to update amount in the account
}
// for testing private methods
private int sum(int num1, int num2){
return num1+num2;
}
}
class AccountDetails{
public long getAmount(long accountNum) throws Exception{
// some database operation returning amount in the account
long amount = 10000L;
return amount;
}
}
Testclass:
package org.mockprivatemethods;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
#RunWith(PowerMockRunner.class)
public class TestAccountDeposit {
#InjectMocks
AccountDeposit accountDeposit;
#Mock
AccountDetails accountDetailsMocks;
#Test
public void testDposit() throws Exception{
long amount = 200;
when(accountDetailsMocks.getAmount(Mockito.anyLong()))
.thenReturn(amount);
// need to mock private method updateAccount
// just like we tested the private method "sum()" using Whitebox
// How to mock this private method updateAccount
long totalAmount = accountDeposit.deposit(12345678L, 50);
assertTrue("Amount in Account(200+50): "+totalAmount , 250==totalAmount);
}
#Test
public void testSum(){
try {
int amount = Whitebox.invokeMethod(accountDeposit, "sum", 20, 30);
assertTrue("Sum of (20,30): "+amount, 50==amount);
} catch (Exception e) {
Assert.fail("testSum() failed with following error: "+e);
}
}
}
We can test the private methods using Whitebox.invokeMethod(). My question is: Is there any to way mock the private method using Whitebox. Can we write something similar to below code to mock the updateAccount() as I do not want any database operation to be performed while testing the Deposit() method?strong text
when(accountDetailsMocks.getAmount(Mockito.anyLong()))
.thenReturn(amount);
Any help is appreciated! Thanks!
I have an actor class EmployeeActor, inside that actor, some other actor is fired using payrollRunActor.tell(). I need to write a JUnit test for EmployeeActor.java, but I don't want to fire payrollRunActor.tell(), means I want to mock it.
Is there a way to do it? I tried a lot, but real payrollRunActor is getting fired.
Here is the actual code of my EmployeeActor class.
package com.test.periodic.actors;
import java.util.List;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.test.avs.domain.boundedcontext.Employee;
import com.test.avs.domain.boundedcontext.PayrollRun;
import com.test.entity.BusinessDTO;
import com.test.periodic.actors.aggregrators.EmployeeAggregator;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.routing.RoundRobinPool;
public class EmployeeActor extends AbstractActor {
private static final Logger logger = LoggerFactory.getLogger(EmployeeActor.class);
private boolean rollup;
public static Props props() {
return Props.create(EmployeeActorTest.class);
}
private List<PayrollRun> payrollRuns;
private String instanceId;
private String employeeAggregatorId;
private Employee employee;
private ActorRef organizationAggregatorActor;
private List<BusinessDTO> businessDTOs;
final ActorSystem payrollRunSystem = ActorSystem.create("payrollRun");
ActorRef employeeAggregator;
public EmployeeActor(ActorRef organizationAggregatorActor, List<PayrollRun> payrollRuns,
Employee employee, List<BusinessDTO> businessDTOs, boolean rollup) {
this.payrollRuns = payrollRuns;
this.employee = employee;
this.organizationAggregatorActor = organizationAggregatorActor;
this.businessDTOs = businessDTOs;
this.rollup = rollup;
}
#Override
public void preStart() throws Exception {
instanceId = RandomStringUtils.randomAlphanumeric(6);
employeeAggregatorId = "employeeAggregator-" + instanceId;
employeeAggregator = getContext().system().actorOf(
Props.create(EmployeeAggregator.class, organizationAggregatorActor, employee),
employeeAggregatorId);
super.preStart();
}
#Override
public Receive createReceive() {
return receiveBuilder().match(Employee.class, employee -> {
if (rollup) {
logger.info("Rollingup business entities.");
employeeAggregator.tell(employee, getSelf());
} else {
ActorRef payrollRunActor = payrollRunSystem.actorOf(new RoundRobinPool(payrollRuns.size())
.props(Props.create(PayrollRunActor.class, employeeAggregator, employee, businessDTOs)));
for (PayrollRun payrollRun : payrollRuns) {
**payrollRunActor.tell(payrollRun, getSelf());**
}
}
}).match(PayrollRun.class, maxPaydatePayrollRun -> {
ActorRef payrollRunActor = payrollRunSystem
.actorOf(Props.create(PayrollRunActor.class, employeeAggregator, employee, businessDTOs));
**payrollRunActor.tell(maxPaydatePayrollRun, getSelf());**
}).build();
}
}
First of all you would have to mock the static method call which is invoked during the creation of class under test. Then make it return a spied object and mock the method you want to avoid calling:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ActorSystem.class)
public void TestClass{
#Test
public void test(){
// Arrange
PowerMockito.mockStatic(ActorSystem.class);
ActorSystem actorSystemMock = Mockito.mock(ActorSystem.class);
Actor actorSpy = Mockito.spy(new Actor());
Mockito.when(ActorSystem.create("payrollRun")).thenReturn(actorSystemSpy);
Mockito.when(actorSystemMock.actorOf(any(RoundRobinPool.class)))
.thenReturn(actorSpy);
Mockito.doNothing().when(actorSpy)
.tell(Mockito.any(PayrollRun.class), Mockito.any(Self.class));
EmployeeActor employeeActor = new EmployeeActor();
// Act and assert...
employeeActor.createReceive();
}
}
Remember that all other methods of actorSystemSpy will be called will real implementation. If you want to mock all of them then use Mockito.mock instead of spy.
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();
From the examples on the PowerMock homepage, I see the following example for partially mocking a private method with Mockito:
#RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
#PrepareForTest(PartialMockClass.class)
public class YourTestCase {
#Test
public void privatePartialMockingWithPowerMock() {
PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());
// use PowerMockito to set up your expectation
PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");
// execute your test
classUnderTest.execute();
// Use PowerMockito.verify() to verify result
PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");
}
However, this approach does not seem to work when the private method we wish to mock is static. I wish to create a partial mock of the below class, with the readFile method mocked:
package org.rich.powermockexample;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import static com.google.common.io.Files.readLines;
public class DataProvider {
public static List<String> getData() {
List<String> data = null;
try {
data = readFile();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
private static List<String> readFile() throws IOException {
File file = new File("/some/path/to/file");
List<String> lines = readLines(file, Charset.forName("utf-8"));
return lines;
}
}
Please could someone let me know how this can be achieved?
After doing a bit more research, it seems that PowerMockito.spy() and PowerMockito.doReturn() are what is required here:
package com.richashworth.powermockexample;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
#RunWith(PowerMockRunner.class)
#PrepareForTest({DataProvider.class})
public class ResultsWriterTest {
private static List<String> mockData = new ArrayList<String>();
private ResultsWriter resultsWriter;
#BeforeClass
public static void setUpOnce() {
final String firstLine = "Line 1";
final String secondLine = "Line 2";
mockData.add(firstLine);
mockData.add(secondLine);
}
#Before
public void setUp() {
resultsWriter = new ResultsWriter();
}
#Test
public void testGetDataAsString() throws Exception {
PowerMockito.spy(DataProvider.class);
PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile");
final String expectedData = "Line 1\nLine 2\n";
final String returnedString = resultsWriter.getDataAsString();
assertEquals(expectedData, returnedString);
}
}
For further details and the complete code listing, check out my blog post here: https://richashworth.com/post/turbocharge-your-mocking-framework-with-powermock/
Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(DataProvider.class)
public class DataProviderTest {
#Test
public void testGetDataWithMockedRead() throws Exception {
mockStaticPartial(DataProvider.class, "readFile");
Method[] methods = MemberMatcher.methods(DataProvider.class, "readFile");
expectPrivate(DataProvider.class, methods[0]).andReturn(Arrays.asList("ohai", "kthxbye"));
replay(DataProvider.class);
List<String> theData = DataProvider.getData();
assertEquals("ohai", theData.get(0));
assertEquals("kthxbye", theData.get(1));
}
}
Class being tested (basically yours):
public class DataProvider {
public static List<String> getData() {
try {
return readFile();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static List<String> readFile() throws IOException {
File file = new File("/some/path/to/file");
return readLines(file, Charset.forName("utf-8"));
}
}
In general, only use static mocking for classes that are beyond your control (e.g. java.io.File). Since DataProvider and readFile are your own, refactor DataProvider into a proper class (i.e. make its methods non-static), pull out readFile into a helper object and then mock that. See this answer https://stackoverflow.com/a/8819339/116509.