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.
Related
I am practising restful api endpoints using https://api.predic8.de/shop/docs
Here is my repo
I am getting a NPE failure when I try to use #InjectMocks during my TDD approach
However, I can make my test pass when I make a direct call in the setup()
vendorService = new VendorServiceImpl(VendorMapper.INSTANCE, vendorRepository);
I wanted to extend my learning by trying to create an endpoint for getting all vendors.
When I employ TDD along the way, but, my test getAllVendors() fails on a NPE when I try to use #InjectMocks but passes when I substitute it for a direct call in the setup() method.
The NPE is linked to the mapper class I think.
Here are the classes that I believe are useful. VendorServiceTest, VendorServiceImpl, VendorMapper.
I have commented out the direct call in the setup as I want to get the test passing using #InjectMocks
package guru.springfamework.services;
import guru.springfamework.api.v1.mapper.VendorMapper; import
guru.springfamework.api.v1.model.VendorDTO; import
guru.springfamework.domain.Vendor; import
guru.springfamework.repositories.VendorRepository; import
org.junit.Before; import org.junit.Test; import
org.mockito.InjectMocks; import org.mockito.Mock; import
org.mockito.MockitoAnnotations; import
org.springframework.test.web.servlet.MockMvc;
import java.util.Arrays; import java.util.List;
import static org.junit.Assert.*; import static
org.mockito.Mockito.when;
public class VendorServiceTest {
public static final String NAME = "Tasty";
public static final Long ID = 1L;
#Mock
VendorMapper vendorMapper;
#Mock
VendorRepository vendorRepository;
#InjectMocks
VendorServiceImpl vendorService;
//VendorService vendorService;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
//vendorService = new VendorServiceImpl(VendorMapper.INSTANCE, vendorRepository);
}
#Test
public void getAllVendors() {
//given
List<Vendor> vendors = Arrays.asList(new Vendor(), new Vendor(), new Vendor());
when(vendorRepository.findAll()).thenReturn(vendors);
//when
List<VendorDTO> vendorDTOList = vendorService.getAllVendors();
//then
assertEquals(3, vendorDTOList.size());
}
#Test
public void findByName() {
}
}
package guru.springfamework.services;
import guru.springfamework.api.v1.mapper.VendorMapper; import
guru.springfamework.api.v1.model.VendorDTO; import
guru.springfamework.repositories.VendorRepository; import
org.springframework.stereotype.Service;
import java.util.List; import java.util.stream.Collectors;
#Service public class VendorServiceImpl implements VendorService {
private final VendorMapper vendorMapper;
private final VendorRepository vendorRepository;
public VendorServiceImpl(VendorMapper vendorMapper, VendorRepository vendorRepository) {
this.vendorMapper = vendorMapper;
this.vendorRepository = vendorRepository;
}
#Override
public List<VendorDTO> getAllVendors() {
return vendorRepository
.findAll()
.stream()
.map(vendor -> {
VendorDTO vendorDTO = vendorMapper.vendorToVendorDTO(vendor);
vendorDTO.setVendorUrl("/api/v1/vendors/" + vendor.getId());
return vendorDTO;
})
.collect(Collectors.toList());
}
#Override
public VendorDTO findByName(String name) {
return vendorMapper.vendorToVendorDTO(vendorRepository.findByName(name));
}
#Override
public VendorDTO getVendorById(Long id) {
return vendorMapper.vendorToVendorDTO(vendorRepository.findById(id).orElseThrow(RuntimeException::new));
}
}
package guru.springfamework.api.v1.mapper;
import guru.springfamework.api.v1.model.VendorDTO; import
guru.springfamework.domain.Vendor; import org.mapstruct.Mapper; import
org.mapstruct.factory.Mappers;
#Mapper public interface VendorMapper {
VendorMapper INSTANCE = Mappers.getMapper(VendorMapper.class);
VendorDTO vendorToVendorDTO(Vendor vendor);
}
Does anyone know where and why I am going wrong?
The problem is that you created mock object for the mapper, but you didn't say what should happen when the method vendorToVendorDTO is called.
Therefore, when that method is called in the next line of code:
VendorDTO vendorDTO = vendorMapper.vendorToVendorDTO(vendor);
It will return null, and then in this line of code:
vendorDTO.setVendorUrl("/api/v1/vendors/" + vendor.getId());
You will get NullPointerException.
To make this work, change your getAllVendors() method as follows:
#Test
public void getAllVendors() {
//given
List<Vendor> vendors = Arrays.asList(new Vendor(), new Vendor(), new Vendor());
VendorDTO mockDto = mock(VendorDTO.class);
when(vendorRepository.findAll()).thenReturn(vendors);
when(vendorMapper.vendorToVendorDTO(any(Vendor.class))).thenReturn(mockDto);
//when
List<VendorDTO> vendorDTOList = vendorService.getAllVendors();
//then
assertEquals(3, vendorDTOList.size());
}
And the test should pass.
Have you tried to put #RunWith(MockitoJUnitRunner.class)/#ExtendsWith(MockitoExtension.class) over your test class?
I have a simple line of Code:
DraftCampaignDetails createdDraft = draftCampaignI.createDraftCampaign(ConvertionUtil
.getDraftCampaignDetailsfromCreateDraftRequest(request));
I am trying to mock it like this:
ConvertionUtil action1 = PowerMockito.mock(ConvertionUtil.class);
when(action1.getDraftCampaignDetailsfromCreateDraftRequest(request)).thenReturn(details);
when(draftCampaignI.createDraftCampaign(details)).thenReturn(details);
But I am getting this error:
when() requires an argument which has to be 'a method call on a mock'.
Adding entire test class for more clarity:
public class DraftCampaignActivityTest {
#Mock
IDraftCampaign draftCampaignI;
/* #Mock
ConvertionUtil util;*/
#Before
#SuppressWarnings("unchecked")
public void setup()
{
MockitoAnnotations.initMocks(this);
}
#Test
public void createDraft_newDraft() {
DraftCampaignActivity draftContoller = new DraftCampaignActivity();
CreateDraftCampaignRequest request = createRequest();
DraftCampaignDetails details = buildDraftDetails();
if(draftCampaignI != null){
System.out.println("sccdscscd");
}
/*
if(util != null) {
System.out.println("wewewew");
}*/
/// ConvertionUtil action1 = PowerMockito.mock(ConvertionUtil.class);
PowerMockito.mockStatic(ConvertionUtil.class);
PowerMockito.when(
ConvertionUtil.getDraftCampaignDetailsfromCreateDraftRequest(request)
).thenReturn(details);
when(draftCampaignI.createDraftCampaign(details)).thenReturn(details);
// when(util.getDraftCampaignDetailsfromCreateDraftRequest(request)).thenReturn(details);
CreateDraftCampaignResponse response = new CreateDraftCampaignResponse();
draftContoller.createDraftCampaign(request);
response.setDraftCampaignId(details.getDraftId());
Assert.assertEquals(response.getDraftCampaignId(),"ww");
}
private DraftCampaignDetails buildDraftDetails() {
DraftCampaignDetails details = new DraftCampaignDetails();
details.setDraftId("ww");
return details;
}
private CreateDraftCampaignRequest createRequest() {
CreateDraftCampaignRequest request = new CreateDraftCampaignRequest();
request.setCampaignInfo("campaignInfo");
request.setMarketplaceId("adadedaedaed");
DraftCampaignDetailsBase base = new DraftCampaignDetailsBase();
Money money = new Money();
money.setCurrencyCode("USD");
money.setMillicents(10L);
base.setCampaignBudget(money);
base.setCampaignName("name");
base.setDraftCampaignState("DRAFT");
request.setDraftCampaignDetailsBase(base);
return request;
//request
}
I am new to Mockito and Powermock. please help! Any help will be greatly appreciated!
To work draftCampaignI must be injected into draftContoller, to do so you need to declare draftContoller as a field of your test class annotated with #InjectMocks, no need to create the instance of DraftCampaignActivity explicitly anymore, leave it to Mockito, as next:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.when;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
public class DraftCampaignActivityTest {
#Mock
IDraftCampaign draftCampaignI;
#InjectMocks
DraftCampaignActivity draftContoller;
#Test
#PrepareForTest(ConvertionUtil.class)
public void createDraft_newDraft() {
CreateDraftCampaignRequest request = new CreateDraftCampaignRequest();
DraftCampaignDetails details = new DraftCampaignDetails();
PowerMockito.mockStatic(ConvertionUtil.class);
PowerMockito.when(
ConvertionUtil.getDraftCampaignDetailsfromCreateDraftRequest(request)
).thenReturn(details);
when(draftCampaignI.createDraftCampaign(details)).thenReturn(details);
draftContoller.createDraftCampaign(request);
}
}
Assuming that the class DraftCampaignActivity is of type:
public class DraftCampaignActivity {
...
private IDraftCampaign draftCampaignI;
...
}
More details about the annotation InjectMocks.
NB: As we use #RunWith(PowerMockRunner.class), we have no need to call MockitoAnnotations.initMocks(this) explicitly as it will be done internally such that the method setup is useless and can be removed.
I have a service/dao layer. Service layer method calls 1st method of dao from which I get response and call the second method in dao passing some arguments including the value from the response of 1st dao method. I tried using mock but its failing with null pointer.
pseudo code is something like below:
Service{
serviceMethod(some_args){
response1 = dao.method1(some_args);
someItem = response1.get("someItem");
/* do some logic on someitem to create otherItem*/
request2.setArgs(someItem);
response2 = dao.method2(request2);
}
}
I have tried to mock as below but its not working.
#Test
public void testPass(){
mockResponse1 = new Response1();
mockRequest2 = new MockRequest2();
when(dao.method1(some_args)).thenReturn(mockResponse1)
mockResponse1.setArgs(some_args);
mockRequest2.setArgs(mockResponse1.getargs());
mockResponse2 = new Response2();
when(dao.method2(mockRequest2)).thenReturn(mockResponse2)
service.serviceMethod(some_args)
}
You could use an ArgumentCaptor to get the value that was passed into dao.method2(...) and then make assertions on that.
For example, say I had this DAO...
public interface DAO {
Response method1(Request request);
Response method2(Request request);
}
And this service...
public class Service {
private DAO dao;
public void setDao(DAO dao) {
this.dao = dao;
}
public Response serviceMethod(Request someArgs) {
Response response1 = dao.method1(someArgs);
String someItem = response1.getTheResponse();
Request request2 = new Request(someItem);
return dao.method2(request2);
}
}
A test for this service could be...
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class ServiceTest {
#Mock
private Request request;
#Mock
private Response response;
#Mock
private Response serviceResponse;
#Mock
private DAO dao;
#InjectMocks
private Service service;
#Captor
private ArgumentCaptor<Request> requestCaptor;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldDoServiceMethod() {
// Set up
when(dao.method1(request)).thenReturn(response);
when(response.getTheResponse()).thenReturn("[ARGUMENT]");
when(dao.method2(any(Request.class))).thenReturn(serviceResponse);
// Code under test
Response actualResponse = service.serviceMethod(request);
// Verification
assertThat(actualResponse).isSameAs(serviceResponse);
verify(dao).method2(requestCaptor.capture());
Request actualSecondRequest = requestCaptor.getValue();
assertThat(actualSecondRequest.getArgs()).isEqualTo("[ARGUMENT]");
}
}
The key line being...
verify(dao).method2(requestCaptor.capture());
This verifies that method2 was called and captures the value that it was called with.
You then get the value...
Request actualSecondRequest = requestCaptor.getValue();
...and you can then verify that the relevant information was set...
assertThat(actualSecondRequest.getArgs()).isEqualTo("[ARGUMENT]");
Hope this helps.
For completeness, here's Request and Response...
public class Request {
private String args;
public Request(String args) {
this.args = args;
}
public String getArgs() {
return args;
}
}
public class Response {
private String theResponse;
public Response(String theResponse) {
this.theResponse = theResponse;
}
public String getTheResponse() {
return theResponse;
}
}
I've stared to use spring's #EventListener annotation to create event handlers that handle my non-spring specific events. Initially everything went pretty well. I used a test to verify that I could put the #EventListener annotation on a method of a abstract class and everything worked as expected.
However, once I started adding generics to the mix I started getting NullPointerExceptions from ApplicationListenerMethodAdapter.java:337.
I've created a test case to illustrate the problem. Currently all the test methods fail with the exception:
java.lang.NullPointerException
at java.lang.Class.isAssignableFrom(Native Method)
at org.springframework.context.event.ApplicationListenerMethodAdapter.getResolvableType(ApplicationListenerMethodAdapter.java:337)
at org.springframework.context.event.ApplicationListenerMethodAdapter.resolveArguments(ApplicationListenerMethodAdapter.java:161)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:142)
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:106)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:348)
When I move the #EventListener annotation down to each concrete listener the exception disappears and things behave as expected with the exception of testSendingEventWithGenericsWithExtendedUniquePayload.
Questions
Q1) Is it a valid usage pattern to put #EventListener on a method of a abstract super class? I was hoping to implement common behavior there.
Q2) I read about implementing ResolvableTypeProvider on my event in the spring docs. My understanding was that this would allow me to avoid having to create many concrete subclasses for each payload type. This is what I'm attempting to test in testSendingEventWithGenericsWithExtendedUniquePayload. I'm expecting the event fired in this test to be handled by TestEventWithGenericsExtendedUniquePayloadListener but it's not. Have I misunderstood something here?
Spring: 4.2.4.RELEASE
Java: 1.8.0_65
Thanks for your help
Oliver
Test Code
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;
import org.springframework.stereotype.Component;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.springframework.core.ResolvableType.*;
/**
* #author Oliver Henlich
*/
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#DirtiesContext
public class EventListenerTest {
private static final Logger log = LoggerFactory.getLogger(EventListenerTest.class);
#Autowired
protected transient ApplicationEventPublisher applicationEventPublisher;
#Test
public void testSendingEvent1() {
log.info("testSendingEvent1");
// this should go to TestEvent1Listener
applicationEventPublisher.publishEvent(new TestEvent1(new UniquePayload()));
}
#Test
public void testSendingEventWithGenerics() {
log.info("testSendingEventWithGenerics");
// this should go to TestEventWithGenericsListener
applicationEventPublisher.publishEvent(new TestEventWithGenerics<>(new UniquePayload()));
}
#Test
public void testSendingEventWithGenericsWithExtendedUniquePayload() {
log.info("testSendingEventWithGenerics");
// I was expecting this to go to TestEventWithGenericsExtendedUniquePayloadListener
applicationEventPublisher.publishEvent(new TestEventWithGenerics<>(new ExtendedUniquePayload()));
}
#Test
public void testSendingEvent2() {
log.info("testSendingEvent2");
// there is no listener for this one
applicationEventPublisher.publishEvent(new TestEvent2(new UniquePayload()));
}
// LISTENERS --------------------------------------------------------------
interface TestDataEventListener<E extends TestDataEvent> {
#SuppressWarnings("unused")
List<String> handleEvent(E event);
}
abstract static class AbstractTestDataEventListener<E extends TestDataEvent> implements TestDataEventListener<E> {
#Override
#EventListener
public final List<String> handleEvent(E event) {
return onEvent(event);
}
public abstract List<String> onEvent(E event);
}
#Component
static final class TestEvent1Listener extends AbstractTestDataEventListener<TestEvent1> {
#Override
public List<String> onEvent(TestEvent1 event) {
log.info("Listener {} handled {}", this, event);
return Collections.emptyList();
}
}
#Component
static final class TestEventWithGenericsListener extends AbstractTestDataEventListener<TestEventWithGenerics> {
#Override
public List<String> onEvent(TestEventWithGenerics event) {
log.info("Listener {} handled {}", this, event);
return Collections.emptyList();
}
}
#Component
static final class TestEventWithGenericsExtendedUniquePayloadListener extends AbstractTestDataEventListener<TestEventWithGenerics<ExtendedUniquePayload>> {
#Override
public List<String> onEvent(TestEventWithGenerics<ExtendedUniquePayload> event) {
log.info("Listener {} handled {}", this, event);
return Collections.emptyList();
}
}
// EVENTS -----------------------------------------------------------------
interface TestDataEvent<T extends Unique> extends ResolvableTypeProvider {
T load();
}
abstract static class AbstractTestDataEvent<T extends Unique> implements TestDataEvent<T> {
protected final UUID uuid;
private final ResolvableType resolvableType;
public AbstractTestDataEvent(T uniqueObject) {
uuid = uniqueObject.getUuid();
ResolvableType temp = ResolvableType.forClass(getClass());
if (temp.hasGenerics()) {
temp = forClassWithGenerics(getClass(), forInstance(uniqueObject));
}
resolvableType = temp;
log.info("class = {} resolvableType = {}", getClass(), resolvableType);
}
#Override
public ResolvableType getResolvableType() {
return resolvableType;
}
}
static final class TestEvent1 extends AbstractTestDataEvent<UniquePayload> {
public TestEvent1(UniquePayload uniqueObject) {
super(uniqueObject);
}
#Override
public UniquePayload load() {
return new UniquePayload(uuid);
}
}
static final class TestEvent2 extends AbstractTestDataEvent<UniquePayload> {
public TestEvent2(UniquePayload uniqueObject) {
super(uniqueObject);
}
#Override
public UniquePayload load() {
return new UniquePayload(uuid);
}
}
static final class TestEventWithGenerics<T extends UniquePayload> extends AbstractTestDataEvent<T> {
public TestEventWithGenerics(T uniqueObject) {
super(uniqueObject);
}
#Override
public T load() {
return (T) new UniquePayload(uuid);
}
}
static class UniquePayload implements Unique {
private final UUID uuid;
public UniquePayload() {
this(UUID.randomUUID());
}
public UniquePayload(UUID uuid) {
this.uuid = uuid;
}
#Override
public UUID getUuid() {
return uuid;
}
}
static class ExtendedUniquePayload extends UniquePayload {
}
interface Unique {
UUID getUuid();
}
#Configuration
#ComponentScan(basePackageClasses = EventListenerTest.class)
public static class ContextConfiguration {
}
}
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());