Mockito mocking get methods from the database services - spring

I am trying to mock a getBy() method after adding an element by a mocked service add.
This is what I have:
FeedItem feedItem = feedServiceTested.createFeedItem("Text Test", "Category Test", "Author Test");
Mockito.verify(feedRepository).add(feedItem);
Mockito.verify(feedRepository).findAllByCategory("Category Test");
However I get the following error:
Wanted but not invoked:
feedRepository.findAllByCategory(
"Category Test"
);
-> at ie.cit.adf.services.FeedServiceImplTest.testSearchFeedItemsByCategory(FeedServiceImplTest.java:55)
However, there were other interactions with this mock:
-> at ie.cit.adf.services.FeedServiceImpl.createFeedItem(FeedServiceImpl.java:44)
at ie.cit.adf.services.FeedServiceImplTest.testSearchFeedItemsByCategory(FeedServiceImplTest.java:55)
Any idea how to mock this findAllByCategory()?
Here are the 2 classes:
Repository:
#Secured("ROLE_USER")
public class JdbcFeedRepository implements FeedRepository {
private JdbcTemplate jdbcTemplate;
private FeedItemsMapper feedItemsMapper = new FeedItemsMapper();
public JdbcFeedRepository(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
#Override
public FeedItem findById(String feedItemId) {
return jdbcTemplate.queryForObject(
"SELECT ID, TEXT, CATEGORY, AUTHOR FROM FEEDITEMS WHERE ID=?",
feedItemsMapper,
feedItemId
);
}
#Override
public List<FeedItem> findAll() {
return jdbcTemplate.query(
"SELECT ID, TEXT, CATEGORY, AUTHOR FROM FEEDITEMS",
feedItemsMapper
);
}
#Override
public List<FeedItem> findAllByCategory(String category) {
return jdbcTemplate.query(
"SELECT ID, TEXT, CATEGORY, AUTHOR FROM FEEDITEMS WHERE CATEGORY=?",
feedItemsMapper,
category
);
}
#Override
public List<FeedItem> findAllByAuthor(String author) {
return jdbcTemplate.query(
"SELECT ID, TEXT, CATEGORY, AUTHOR FROM FEEDITEMS WHERE AUTHOR=?",
feedItemsMapper,
author
);
}
#Override
public void add(FeedItem feedItem) {
jdbcTemplate.update(
"INSERT INTO FEEDITEMS VALUES(?,?,?,?)",
feedItem.getId(),
feedItem.getText(),
feedItem.getCategory(),
feedItem.getAuthor()
);
}
#Override
public void delete(String feedItemId) {
jdbcTemplate.update("DELETE FROM FEEDITEMS WHERE ID=?", feedItemId);
}
/**
* Returns the name of the currently logged in Author.
*
* #return String
*/
private String getCurrentUser() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
}
class FeedItemsMapper implements RowMapper<FeedItem> {
#Override
public FeedItem mapRow(ResultSet rs, int rowNum) throws SQLException {
FeedItem feedItem = new FeedItem();
feedItem.setId(rs.getString("ID"));
feedItem.setText(rs.getString("TEXT"));
feedItem.setCategory(rs.getString("CATEGORY"));
feedItem.setAuthor(rs.getString("AUTHOR"));
return feedItem;
}
}
Service:
#Transactional
public class FeedServiceImpl implements FeedService {
private FeedRepository repo;
public FeedServiceImpl(FeedRepository repo) {
this.repo = repo;
}
#Override
public FeedItem get(String feedItemId) {
return repo.findById(feedItemId);
}
#Override
public List<FeedItem> getAllFeedItems() {
return repo.findAll();
}
#Override
public List<FeedItem> getAllFeedItemsByCategory(String category) {
return repo.findAllByCategory(category);
}
#Override
public List<FeedItem> getAuthorFeedItems(String author) {
return repo.findAllByAuthor(author);
}
#Override
public FeedItem createFeedItem(String text, String category, String author) {
FeedItem feedItem = new FeedItem();
feedItem.setText(text);
feedItem.setCategory(category);
feedItem.setAuthor(author);
repo.add(feedItem);
return feedItem;
}
#Override
public void delete(String feedItemId) {
repo.delete(feedItemId);
}
}

It seems your code never calls:
feedRepository.findAllByCategory("Category Test");
But you added a verifier for it. Mockito verify ensures the method is called one time in your test. When this did not happen its complains with an exception.
Your test calls:
feedServiceTested.createFeedItem(...)
Which only calls the following methods on repo:
add(feedItem)
Which is your first verify. So at the moment it seems your code did not use findAllByCategory and so does the verify throws this exception.
Or is there a call in FeedItem to the repo? Then please provide the code for this class too.

Related

How to register hibernate custom multiple EventListeners

My scenario is need yo track entity property changes. I have used Hibernate PostUpdateEventListener interface to achieve that.
Following is my generic event listener class.
public abstract class EventListener<DOMAIN extends BaseModel> implements PostUpdateEventListener {
public abstract LogSupport getService();
public abstract BaseModel getLogDomain(DOMAIN domain);
#SuppressWarnings("unchecked")
private DOMAIN getDomain(BaseModel model) {
return (DOMAIN) model;
}
public void postUpdate(PostUpdateEvent event, BaseModel model) {
getService().createUpdateLog(getDomain(model), getPostUpdateEventNotes(event));
}
private String getPostUpdateEventNotes(PostUpdateEvent event) {
StringBuilder sb = new StringBuilder();
for (int p : event.getDirtyProperties()) {
sb.append("\t");
sb.append(event.getPersister().getEntityMetamodel().getProperties()[p].getName());
sb.append(" (Old value: ")
.append(event.getOldState()[p])
.append(", New value: ")
.append(event.getState()[p])
.append(")\n");
}
System.out.println(sb.toString());
return sb.toString();
}
}
And this is my custom entity listener.
#Component
public class AssetEventListener extends EventListener<Asset> {
private static final long serialVersionUID = -6076678526514705909L;
#Autowired
#Qualifier("assetLogService")
private LogSupport logSupport;
#Override
public LogSupport getService() {
AutowireHelper.autowire(this, logSupport);
return logSupport;
}
#PostPersist
public void onPostInsert(PostInsertEvent event) {
if (event.getEntity() instanceof BaseModel){
super.postPersist( event, (BaseModel) event.getEntity() );
}
}
#Override
public void onPostUpdate(PostUpdateEvent event) {
if (event.getEntity() instanceof BaseModel){
super.postUpdate( event, (BaseModel) event.getEntity() );
}
}
#Override
public BaseModel getLogDomain(Asset domain) {
return domain;
}
#Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
And I called it from #EntityListeners
#Entity
#Table(name = "tbl_asset")
#EntityListeners({ AssetEventListener.class })
public class Asset extends BaseModel {
}
Listener not call when update the entity. Any help would be greatly appreciated.
Thanks,

Spring + Hibernate + TestNG + Mocking nothing persist, nothing is readed in test

Fighting with TestNG, Spring an Hibernate. I'm writing test for Service class, and it's always failure. But without test class works fine. So App is working, but tests don't want to.
Here is my test class
#Transactional
public class BorrowerServiceTest {
#Mock
BorrowerDAOImpl borrowerDAO;
#InjectMocks
BorrowerService borrowerService;
#BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void persistTest() {
Borrower borrower = new Borrower.BorrowerBuilder().firstName("Lars").lastName("Urlich").adress("LA")
.phoneNumber("900900990").build();
borrowerService.persist(borrower);
List<Borrower> borrowerList = borrowerService.getBorrowerByName("Lars Urlich");
Assert.assertEquals(true, borrower.equals(borrowerList.get(0)));
}
}
My BorrowerService:
#Service("borrowerService")
#Transactional
public class BorrowerService {
#Autowired
private BorrowerDAO borrowerDAO;
public List<Borrower> getBorrowers() {
return borrowerDAO.getBorrowers();
}
public List<Borrower> getBorrowerByName(String name) {
return borrowerDAO.getBorrowerByName(name);
}
public boolean removeBorrower(Borrower borrower) {
return borrowerDAO.removeBorrower(borrower);
}
public boolean persist(Borrower borrower) {
return borrowerDAO.persist(borrower);
}
}
My BorrowerDAOImpl:
#Repository("borrowerDAO")
#Transactional
public class BorrowerDAOImpl extends DAO implements BorrowerDAO {
#Override
public List<Borrower> getBorrowers() {
List<Borrower> borrowerList = null;
Query query = entityManager.createQuery("SELECT B FROM Borrower B");
borrowerList = query.getResultList();
return borrowerList;
}
#Override
public List<Borrower> getBorrowerByName(String name) {
List<Borrower> borrowerList = null;
String[] values = name.split(" ");
Query query = entityManager.createQuery("SELECT B FROM Borrower B WHERE B.firstName LIKE '" + values[0]
+ "' AND B.lastName LIKE '" + values[1] + "'");
borrowerList = query.getResultList();
return borrowerList;
}
#Override
public boolean removeBorrower(Borrower borrower) {
String firstName = borrower.getFirstName();
String lastName = borrower.getLastName();
Query query = entityManager
.createQuery("DELETE Borrower where FIRST_NAME LIKE :FirstName AND LAST_NAME LIKE :LastName");
query.setParameter("FirstName", firstName);
query.setParameter("LastName", lastName);
query.executeUpdate();
return true;
}
#Override
public boolean persist(Borrower borrower) {
entityManager.persist(borrower);
return true;
}
}
and abstract DAO:
#Repository
#Transactional
public abstract class DAO {
#PersistenceContext
protected EntityManager entityManager;
}
Maven returns failure:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
at java.util.LinkedList.get(LinkedList.java:476)
at com.me.service.test.BorrowerServiceTest.persistTest(BorrowerServiceTest.java:41)
I also had to fight with this. The problem here is that your test runs in it's own transaction, so nothing will be committed during method's execution. Now here is what I did:
public class IntegrationTest extends SomeTestBase
{
#Autowired
private PlatformTransactionManager platformTransactionManager;
private TransactionTemplate transactionTemplate;
#Autowired
private BeanToTest beanToTest;
#Override
#Before
public void setup()
{
super.setup();
this.transactionTemplate = new TransactionTemplate(this.platformTransactionManager);
}
#Test
public void fooTest()
{
// given
// when
boolean result = this.transactionTemplate.execute(new TransactionCallback<Boolean>()
{
#Override
public Boolean doInTransaction(TransactionStatus status)
{
return IntegrationTest.this.beanToTest.foo();
}
});
// then
}
}
This allows you to have methods execute within a separate transaction. Please note that you might declare some variables as final.
Hope that helps.
Check the Spring documentation: it looks your test class should extend AbstractTestNGSpringContextTests.
Use #Commit annotation on the whole test class or even method to persist changes made in the test. For more information https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#commit

Axon Event Handler not Working

I am developing a small cqrs implementation and I am very new to it.
I want to segregate each handlers(Command and Event) from aggregate and
make sure all are working well. The command handler are getting triggered
from controller but from there event handlers are not triggered. Could
anyone Please help on this.
public class User extends AbstractAnnotatedAggregateRoot<String> {
/**
*
*/
private static final long serialVersionUID = 1L;
#AggregateIdentifier
private String userId;
private String userName;
private String age;
public User() {
}
public User(String userid) {
this.userId=userid;
}
#Override
public String getIdentifier() {
return this.userId;
}
public void createuserEvent(UserCommand command){
apply(new UserEvent(command.getUserId()));
}
#EventSourcingHandler
public void applyAccountCreation(UserEvent event) {
this.userId = event.getUserId();
}
}
public class UserCommand {
private final String userId;
public UserCommand(String userid) {
this.userId = userid;
}
public String getUserId() {
return userId;
}
}
#Component
public class UserCommandHandler {
#CommandHandler
public void userCreateCommand(UserCommand command) {
User user = new User(command.getUserId());
user.createuserEvent(command);
}
}
public class UserEvent {
private final String userId;
public UserEvent(String userid) {
this.userId = userid;
}
public String getUserId() {
return userId;
}
}
#Component
public class UserEventHandler {
#EventHandler
public void createUser(UserEvent userEvent) {
System.out.println("Event triggered");
}
}
#Configuration
#AnnotationDriven
public class AppConfiguration {
#Bean
public SimpleCommandBus commandBus() {
SimpleCommandBus simpleCommandBus = new SimpleCommandBus();
return simpleCommandBus;
}
#Bean
public Cluster normalCluster() {
SimpleCluster simpleCluster = new SimpleCluster("simpleCluster");
return simpleCluster;
}
#Bean
public ClusterSelector clusterSelector() {
Map<String, Cluster> clusterMap = new HashMap<>();
clusterMap.put("com.user.event.handler", normalCluster());
//clusterMap.put("exploringaxon.replay", replayCluster());
return new ClassNamePrefixClusterSelector(clusterMap);
}
#Bean
public EventBus clusteringEventBus() {
ClusteringEventBus clusteringEventBus = new ClusteringEventBus(clusterSelector(), terminal());
return clusteringEventBus;
}
#Bean
public EventBusTerminal terminal() {
return new EventBusTerminal() {
#Override
public void publish(EventMessage... events) {
normalCluster().publish(events);
}
#Override
public void onClusterCreated(Cluster cluster) {
}
};
}
#Bean
public DefaultCommandGateway commandGateway() {
return new DefaultCommandGateway(commandBus());
}
#Bean
public Repository<User> eventSourcingRepository() {
EventStore eventStore = new FileSystemEventStore(new SimpleEventFileResolver(new File("D://sevents.txt")));
EventSourcingRepository eventSourcingRepository = new EventSourcingRepository(User.class, eventStore);
eventSourcingRepository.setEventBus(clusteringEventBus());
AnnotationEventListenerAdapter.subscribe(new UserEventHandler(), clusteringEventBus());
return eventSourcingRepository;
}
}
As far as I can tell, the only thing missing is that you aren't adding the User Aggregate to a Repository. By adding it to the Repository, the User is persisted (either by storing the generated events, in the case of Event Sourcing, or its state otherwise) and all Events generated by the Command Handler (including the Aggregate) are published to the Event Bus.
Note that the Aggregate's #EventSourcingHandlers are invoked immediately, but any external #EventHandlers are only invoked after the command handler has been executed.

How to use #ModelAttribute annotation to pass an object to the database?

I am going to use #ModelAttribute instead of #RequestParam to bind the user input and write it to the database. I am just confused when the #ModelAttribute bind the data in my request handler method (#ModelAttribute book Book) as an book object then how should I pass this object to the database? Normally using #RequestParam I bind the user inputs variable by variable according to my model class and then I send them to the db using the related DAO method. I show my classes in below. Can anybody say how my request handler method should look like if I use #ModelAttribute?
Model Class:
#Component
public class Book {
int bookId;
String title;
Author author;
Publisher publisher;
public int getBookId() {
return bookId;
}
public void setBookId(int bookId) {
this.bookId = bookId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
}
DAO:
public class BookDAO extends JdbcDaoSupport {
#Autowired
AuthorDAO authorDAO;
#Autowired
PublisherDAO publisherDAO;
public void addBook(String title, int authorId, int publisherId)
throws ClassNotFoundException, SQLException {
String sql = "insert into tbl_book (title, authId, pubId) values (?, ?, ?)";
this.getJdbcTemplate().update(sql, new Object[]{title, authorId, publisherId});
}
}
Service:
#Service
public class BookService {
#Autowired
BookDAO bookDAO;
public Book getBookById(int bookId) throws ClassNotFoundException,
SQLException {
return bookDAO.getBookById(bookId);
}
public List<Book> getAllBooks() throws ClassNotFoundException,
SQLException {
List<Book> bookList = bookDAO.getAllBooks();
return bookList;
}
public void addBook(String title, int authorId, int publisherId) throws ClassNotFoundException,
SQLException {
bookDAO.addBook(title, authorId, publisherId);
}
}
Controller:
#Controller
public class BookController {
#RequestMapping(value = "/addBookExecution", method = equestMethod.POST)
protected ModelAndView addBookExecution(#RequestParam String title,
#RequestParam int authorId, #RequestParam int blisherId)
throws ClassNotFoundException, SQLException {
bookService.addBook(title, authorId, publisherId);
ModelAndView model = new ModelAndView("adminFunctionsPage");
model.addObject("Msg", "Your request has been processed successfully.");
return model;
}
}
Your form should have parameters names as your book object, check below sample code
<form >
<input type="text" name="authorId"/>
<input type="text" name="authorName"/>
etc...
</form>
Book.java
class Book{
Integer authorId;
String authorName;
etc..
}
#RequestMapping(value = "/addBookExecution", method = equestMethod.POST)
protected ModelAndView addBookExecution(#ModelAttribute Book book)
throws ClassNotFoundException, SQLException {
bookService.addBook(book);
ModelAndView model = new ModelAndView("adminFunctionsPage");
model.addObject("Msg", "Your request has been processed successfully.");
return model;
}

smartgwt listgrid RestDataSource not populating

Im new using this front end framework application...
I recently started to work with smartgwt and i'm bulding a new application with a Spring MVC integration.
I'm using a ListGrid with a RestDataSource (Consume the Rest service with mvc:annotation-driven for plain JSON)
I can see that the servaice gets consuming properly perhaps my grid is never shown with the data in it.
Can someone help me here ?
Here's my ListGrid class
public class ListGrid extends com.smartgwt.client.widgets.grid.ListGrid {
private final SpringJSONDataSource springJSONDataSource;
public ListGrid(List<DataSourceField> fields) {
this(new PatientDataSource(fields));
}
public ListGrid(SpringJSONDataSource springJSONDataSource) {
this.springJSONDataSource = springJSONDataSource;
init();
}
private void init() {
setAutoFetchData(true);
setAlternateRecordStyles(true);
setEmptyCellValue("???");
setDataPageSize(50);
setDataSource(springJSONDataSource);
}
}
Now there's the DataSource implmentation
public abstract class SpringJSONDataSource extends RestDataSource {
protected final HTTPMethod httpMethod;
public SpringJSONDataSource(List<DataSourceField> fields) {
this(fields, HTTPMethod.POST);
}
public SpringJSONDataSource(List<DataSourceField> fields, HTTPMethod httpMethod) {
this.httpMethod = httpMethod;
setDataFormat(DSDataFormat.JSON);
addDataSourceFields(fields);
setOperationBindings(getFetch());
addURLs();
}
private void addURLs() {
if(getUpdateDataURL() != null)
setUpdateDataURL(getUpdateDataURL());
if(getRemoveDataURL() != null)
setRemoveDataURL(getRemoveDataURL());
if(getAddDataURL() != null)
setAddDataURL(getAddDataURL());
if(getFetchDataURL() != null)
setFetchDataURL(getFetchDataURL());
}
private void addDataSourceFields(List<DataSourceField> fields) {
for (DataSourceField dataSourceField : fields) {
addField(dataSourceField);
}
}
protected abstract OperationBinding getFetch();
protected abstract OperationBinding getRemove();
protected abstract OperationBinding getAdd();
protected abstract OperationBinding getUpdate();
public abstract String getUpdateDataURL();
public abstract String getRemoveDataURL();
public abstract String getAddDataURL();
public abstract String getFetchDataURL();
}
The class PatientDataSource that extends SpringJSONDataSource
public class PatientDataSource extends SpringJSONDataSource {
public PatientDataSource(List<DataSourceField> fields) {
super(fields);
setPrettyPrintJSON(true);
}
#Override
protected OperationBinding getFetch() {
OperationBinding fetch = new OperationBinding();
fetch.setOperationType(DSOperationType.FETCH);
fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
DSRequest fetchProps = new DSRequest();
fetchProps.setHttpMethod(httpMethod.toString());
fetch.setRequestProperties(fetchProps);
return fetch;
}
#Override
public String getFetchDataURL() {
return "/spring/fetchPatients";
}
#Override
protected OperationBinding getRemove() {
return null;
}
#Override
public String getRemoveDataURL() {
return null;
}
#Override
protected OperationBinding getAdd() {
return null;
}
#Override
public String getAddDataURL() {
return null;
}
#Override
protected OperationBinding getUpdate() {
return null;
}
#Override
public String getUpdateDataURL() {
return null;
}
}
My spring controller PatientControler
#Controller
public class PatienController {
Logger logger = Logger.getLogger(PatienController.class);
#Autowired
private PatientServices patientServices;
#RequestMapping(value = "/patientTest", method = RequestMethod.GET)
#ResponseBody
public Object getTest()
{
return patientServices.getAllPatients();
}
#RequestMapping(value = "/fetchPatients", method = RequestMethod.POST)
#ResponseBody
public Object getAllPatients()
{
return patientServices.getAllPatients();
}
}
PatientServiceImpl
public class PatientServicesImpl implements PatientServices {
public List<Patient> getAllPatients() {
List<Patient> patients = new ArrayList<Patient>();
Patient patient;
for(int i = 0 ; i < 500 ; i++){
patient = new Patient();
patient.setDateOfBirth(new Date());
patient.setFirstName("Joe");
patient.setMiddleName("Moe");
patient.setLastName("Blow");
patient.setLastConsultation(new Date());
patient.setSex(Sex.M);
patients.add(patient);
}
return patients;
}
}
*Im Really stuck right now i've been looking for all type of answers .... but so far nothing worked when i tried to override the transformResponse from my RestDataSource impentation the parameter "data" as an OBJECT, returns me an array [object Object],[object Object],[object Object],[object Object],[object Object] *
The Data which is transferred from the RestDataSource has a specific format which is described in the JavaDoc of the RestDataSource
Your server must understand the request and send back a valid response.
At the moment your example doesn't seem to honour the contract.
To debug the traffic send to and from your server you can use the SmartClient-Console. You can open it by a browser bookmark like this:
javascript:isc.showConsole()
Of cause you need to deploy this console by adding the following module to your gwt.xml
<inherits name="com.smartclient.tools.SmartClientTools"/>
Now go to the RPC Tab and check Track-RPCs

Resources