i'm testing my web-app with junit and mockito (for business layer).
i have an entity:
#Entity
#Table(name = "brand")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Brand.findAll", query = "SELECT b FROM Brand b"),
#NamedQuery(name = "Brand.findByOid", query = "SELECT b FROM Brand b WHERE b.oid = :oid"),
#NamedQuery(name = "Brand.findByName", query = "SELECT b FROM Brand b WHERE b.name = :name")})
public class Brand implements Serializable {
...
and a session bean
#Stateless
public class BrandFacade extends AbstractFacade<Brand> {
#PersistenceContext(unitName = "MyWheelJSFPU")
private EntityManager em;
public void setEm(EntityManager em) {
this.em = em;
}
...
#Override
public List<Brand> findAll(){
return em.createNamedQuery("Brand.findAll", Brand.class).getResultList();
}
...
now i want to test .findAll
public class BrandFacadeTest {
#Mock
private EntityManager mockedEntityManager;
#Mock
private TypedQuery mockedQuery;
private BrandFacade brandFacade;
public BrandFacadeTest() {
}
#BeforeClass
public static void setUpClass() {
System.out.println("Start BrandFacadeTest");
}
#AfterClass
public static void tearDownClass() {
}
#Before
public void initDependencies() {
brandFacade=new BrandFacade();
brandFacade.setEm(mockedEntityManager);
System.out.println("mockEmCreated");
}
/**
* Test of findAll method, of class BrandFacade.
*/
#Test
public void testFindAll() {
System.out.println("findAll");
List<Brand> brands=new ArrayList<>();
when(mockedEntityManager.createNamedQuery("Brand.findAll", Brand.class)).thenReturn(mockedQuery);
when(mockedQuery.getResultList()).thenReturn(brands);
int initNumber=brandFacade.findAll().size();
//creating Brand
Brand b1 = new Brand(1, "mo");
brandFacade.create(b1);
verify(mockedEntityManager, times(1)).persist(any());
brands.add(b1);
assertEquals("error",initNumber+1, brandFacade.findAll().size());
}
...
at this line
when(mockedEntityManager.createNamedQuery("Brand.findAll", Brand.class)).thenReturn(mockedQuery);
it returns a java.lang.nullpointerexception...why??? what's the problem?
i made exactly the same for another entity and it work!
If you want to use the #Mock annotation, you must run the unittest either with MockitoJUnitRunner, or set the following in your test case #Before clause:
MockitoAnnotations.initMocks(BrandFacadeTest);
See here: http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Mockito.html#mock_annotation
Related
I'm using jquery Datatables together with Spring JPA.
I want to create a custom Query so that my Datatable will show a list of items based on the id of a ManyToOne related object.
PS. I have obviously declared Repositories, Mapper and Entities for these DTOs, I'm just avoiding to write all the classes because I find it useless.
public class SezioniDTO {
private static final long serialVersionUID = 1L;
private long id;
private LocalDate sezDtaggiornamento;
private Comune Comune;
}
public class Comune {
private static final long serialVersionUID = 1L;
private long id;
private String comCap;
private String comCodbelfiore;
private String comCodcomune;
}
These are my classes (i use mapstruct to map the dtos from the entities).
How can i use criteria builder inside my repository and services to search for Sezionis based on Comunes id?
I'm new to QueryDSL and Specifications, i just would like to obtain something like this:
#Query("Select * from Sezioni s WHERE s.id_Comune = :id", native="true")
public DataTablesOutput <Object> findByField (#Param(value="id", input);
This is the current Service Implementation
#Service
public class SezioniServiceImpl implements SezioniService{
#Autowired
SezioniRepository repo;
#Autowired
SezioniMapper mapper;
#Autowired
SezioniSpecifications sezSpec;
#Override
public List<SezioniDTO> findAll() {
return repo.findAll().stream().map(x -> mapper.entityToDto(x, new CycleAvoidingMappingContext()))
.collect(Collectors.toList());
}
#Override
public List<SezioniDTO> findByIdComune(Long idcom){
return repo.findSezionibyIdComune(idcom).stream().map(x -> mapper.entityToDto(x, new CycleAvoidingMappingContext()))
.collect(Collectors.toList());
}
#Override
public SezioniDTO save(SezioniDTO entity) {
return null;
}
#Override
public Optional<SezioniDTO> findById(Long id) {
// TODO Auto-generated method stub
return null;
}
#Override
public void delete(SezioniDTO entity) {
// TODO Auto-generated method stub
}
#Override
public void deleteById(Long id) {
// TODO Auto-generated method stub
}
#Override
public long count() {
// TODO Auto-generated method stub
return 0;
}
#Override
public DataTablesOutput<SezioniDTO> getSezioniTable(#Valid DataTablesInput input) {
return repo.findAll(input, null, null, a -> mapper.entityToDto(a, new CycleAvoidingMappingContext()) );
}
}
and the current Repository for SezioniDTO
#Repository
public interface SezioniRepository extends JpaRepository<Sezione,Long>, JpaSpecificationExecutor<Sezione>, DataTablesRepository<Sezione,Long> {
#Query(value = "SELECT * FROM db.sezione WHERE sez_com_prg = :id ORDER BY sez_numsezione", nativeQuery = true)
public List <Sezione> findSezionibyIdCom(#Param(value = "id") Long id);
}
Where Sezione is the current Entity. As you can see, it extends , and DataTablesOutput work only with Specifications, which I haven't understood at all.
I simply would like to create a method similar to the public List I have in the repo, but with a DataTablesOutput return instead.
Define Entities:
#Entity
public class Sezioni {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private LocalDate sezDtaggiornamento;
#OneToOne(cascade = {CascadeType.ALL})
#JoinColumn(name = "comune_id")
private Comune Comune;
// getters & setter are omitted
}
and
#Entity
public class Comune {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String comCap;
private String comCodbelfiore;
private String comCodcomune;
// getters & setter are omitted
}
Define repository
#Repository
public interface SezioniRepository extends JpaRepository<Sezioni, Long> {
#Query("select s from Sezioni s where s.Comune.id = :id")
List<Sezioni> findByComuneId(Long id);
}
Use (here in test)
#DataJpaTest
class SezioniRepositoryTest {
#Autowired
SezioniRepository sezioniRepository;
#BeforeEach
void setUp() {
Comune comune = new Comune();
comune.setComCap("cap42");
comune.setComCodcomune("cod43");
Sezioni sezioni = new Sezioni();
sezioni.setComune(comune);
sezioni.setSezDtaggiornamento(LocalDate.of(1970, 1, 1));
sezioniRepository.save(sezioni);
}
#Test
void test() {
List<Sezioni> sezionis = sezioniRepository.findByComuneId(1L);
assertEquals(1, sezionis.size());
assertEquals("cap42",sezionis.get(0).getComune().getComCap());
}
}
Next you can use MapStruct to map entities into DTO (if you prefer to expose DTO on your API)
Criteria Builder's advantage is to build queries dynamically upon your business login needs:
Consider next example:
#Service
public class SezioniQuery {
#PersistenceContext
private EntityManager entityManager;
List<Sezioni> select(TriFunction<CriteriaBuilder, Root<Sezioni>, CriteriaQuery<Sezioni>, CriteriaQuery<Sezioni>> builder) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Sezioni> query = criteriaBuilder.createQuery(Sezioni.class);
// SQL FROM clause
Root<Sezioni> from = query.from(Sezioni.class);
// SQL SELECT clause
CriteriaQuery<Sezioni> select = query.select(from);
// build WHERE somewhere later
CriteriaQuery<Sezioni> apply = builder.apply(criteriaBuilder, from, query);
// execute
TypedQuery<Sezioni> typedQuery = entityManager.createQuery(apply);
return typedQuery.getResultList();
}
}
^^ here we define boilerplate.
Next we can reuse it to build different queires:
// #BeforeEach void setUp() {...} omitted see prev. answer
#Test
void testEqual() {
Long id = 1L;
List<Sezioni> sezionis = sezioniQuery.select((cb, from, query) ->
// WHERE id=1
query.where(cb.equal(from.get("id"), id)));
assertEquals(1, sezionis.size());
assertEquals("cap42",sezionis.get(0).getComune().getComCap());
}
#Test
void testGreater() {
List<Sezioni> sezionis = sezioniQuery.select((cb, from, query) ->
// WHERE id > 0
query.where(cb.gt(from.get("id"), 0)));
assertEquals(1, sezionis.size());
assertEquals("cap42",sezionis.get(0).getComune().getComCap());
}
So, using CriteriaBuilder you can build queries dynamically but this requires a bit more code, non-type-safe code.
Whereas JpaRepository extension is type-safe but non-dynamiŃ
I have to write some junit test cases to check entity. I'm using postgres as my database.
My entity class
#Entity
#Table(name = "display")
public class Display {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String group;
public Display() {
}
public Display(Long id, String title, String grp) {
this.id = id;
this.title= title;
this.group= grp;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return this.id;
}
public void setGroup(String id) {
this.group = id;
}
public String getGroup() {
return this.group;
}
public void settitle(String title) {
this.title = title;
}
public String gettitle() {
return this.title;
}
}
My repository
#Repository
public interface DisplayRepository extends CrudRepository<Display, Long> {
}
Interface
public interface IDisplayService {
List<Display> findAll();
}
Service class
#Service
public class DisplayService implements IDisplayService {
#Autowired
private DisplayRepository repository;
#Override
public List<Display> findAll() {
List<Display> d = (List<Display>) repository.findAll();
return d;
}
}
I tried writing junit test cases but I get Could'nt load Application. Whats the right way to write junit test cases for this?
This is the test case I wrote for service
folder : test/java/example/demo/Test.java
#RunWith(MockitoJUnitRunner.class)
#TestPropertySource("classpath:conn.properties")
public class DisplayServiceTest {
#Value("${id}")
private String value;
#Mock
private DisplayRepository DisplayReps;
#InjectMocks
private DisplayService DisplayService;
#Test
public void whenFindAll_thenReturnProductList() {
Menu m = new Menu()
m.setId(value);
List<Display> expectedDisplay = Arrays.asList(m);
doReturn(expectedDisplay).when(DisplayReps).findAll();
List<Display> actualDisplay = DisplayService.findAll();
assertThat(actualDisplay).isEqualTo(expectedDisplay);
}
in test/java/example/demo/resources
conn.properties
id=2
Its returning 0 for value
Whats the issue?
Thanks
I have managed to make your code to work. I will post only the changed classes:
The interface:
public interface DisplayRepository extends CrudRepository<Display, Long> {
Optional<Display> findByTitle(String name);
}
The test class:
#RunWith(SpringRunner.class)
#AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
#DataJpaTest
public class DisplayRepositoryTest {
#Autowired
private TestEntityManager testEntityManager;
#Autowired
private DisplayRepository productRespository;
#Before()
public void setUp(){
Display m = new Display();
// m.setId(2L); // The ID is autogenerated; can retrieve it from the persistAndFlush result
m.setCategory("Group1");
m.setTitle("Product2");
testEntityManager.persistAndFlush(m);
}
#Test
public void whenFindByName_thenReturnProduct() {
// when
Display product = productRespository.findByTitle("Product2").orElseThrow(() -> new RuntimeException("Product not found"));
// then
assertThat(product.getTitle()).isEqualTo("Product2");
}
#Test
public void whenFindAll_thenReturnProductList() {
// when
List<Display> products = (List<Display>) productRespository.findAll();
// then
assertThat(products).hasSize(1);
}
}
When trying to run the code you provided, there were a few issues:
you were using the reserved word group as a field in the Display class. Because of this, Hibernate couldn't create the table, so I renamed it to category.
there was a compilation issue because the method findByName wasn't defined in the repository; also, there was no field name in the Display class to which the mapping to be made; because of this, I've added the method findByTitle because it's an existing field and it seemed to match the value you queried in the test method.
because the ID field is autogenerated, the test setup() failed when persisting the Display.
If you want to use #Mock for mocking classes, you must call:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
You can then mock responses as usual: Mockito.when(DisplayReps.findByTitle("A")).thenReturn(Optional.of(new Display(2L, "ALFA", "GRP1")));
First time using EasyMock and Spring together.
I have the test class:
#RunWith(EasyMockRunner.class)
public class ProjectServiceTest {
#Mock
private ProjectRepository projectRepositoryMock;
#TestSubject
private ProjectService service new ProjectService();
#Before
public void setUp() throws Exception {
Project project = new Project("Project");
EasyMock.expect(projectRepositoryMock.findOne(1)).andReturn(project);
}
#After
public void tearDown() throws Exception {
}
#Test
public void getProjectById() throws Exception {
System.out.println(this.service.getProjectById(1);
}
This is my project entity:
#Entity
#Table(name = "Project")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String projectName;
public Project(){
}
public Project(String projectName) {
this.projectNaam = projectName;
}
It also has the usual getters and setters.
My repository just extends the JpaRepository.
And this is my ProjectService class
#Service
public class ProjectService {
#Autowired
private ProjectRepository projectRepository;
public ProjectService(){
}
public Project getProjectById(Integer id){
return this.projectRepository.findOne(id);
}
public void saveProject(Project project){
this.projectRepository.save(project);
}
public void deleteProject(Integer id){
this.projectRepository.delete(id);
}
public List<Project> getAllProjects(){
return this.projectRepository.findAll();
}
public Project findProjectById(Integer id){
return this.projectRepository.findOne(id);
}
}
My test failed so that's why I use system.out.println to figure out whats going on. It prints: null.
I don't understand this. #Mock and #TestSubject seems good, becauase I want to test the service and mock the repository.
Instead of
System.out.println(this.service.getProjectById(1);
I tried
System.out.println(this.projectRepositoryMock.findOne(1));
But this also returns null.
You need to put the mock in replay mode. Try
#Before
public void setUp() throws Exception {
Project project = new Project("Project");
EasyMock.expect(projectRepositoryMock.findOne(1)).andReturn(project);
EasyMock.replay(projectRepositoryMock);
}
My professor gave a sample Spring MVC ORM project with Hibernate but I can not figure out the sequence of events involved, in particular about the usage of service business object.
This is just a little part of the project, just to make my ideas clearer.
domain:
#Entity
#Table(name = "department")
public class Department implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long uid;
private String name;
#OneToMany(mappedBy="department",cascade=CascadeType.PERSIST)
private List<Employee> employees = new ArrayList<Employee>();
public Department() {
}
public Department(String name) {
this.name = name;
}
// getters, setters, hashcode() and equals(), toString()...
controller:
#Controller
#RequestMapping("/department")
public class DepartmentController {
#Autowired
#Qualifier("departmentBO")
private DepartmentBO departmentBO;
static final Logger logger = Logger.getLogger(DepartmentController.class);
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String departmentHome(Model model) {
logger.debug("department home() invoked");
List<Department> list = departmentBO.findAllDepartments();
model.addAttribute("list", list);
return "departments";
}
// i'll paste just the first controller ;)
business:
public interface DepartmentBO {
public void delete(long uid);
public List<Department> findAllDepartments();
public Department findByUid(Long uid);
public void save(Department department);
public void update(Department department);
}
business/impl:
#Service
#Transactional
public class DepartmentBoImpl implements DepartmentBO {
#Autowired
private DepartmentDAO departmentDao;
static final Logger logger = Logger.getLogger(DepartmentBoImpl.class);
#Override
public void save(Department department) {
departmentDao.save(department);
}
#Override
public void update(Department department) {
departmentDao.update(department);
}
#Override
public void delete(long uid) {
departmentDao.delete(uid);
}
#Override
public List<Department> findAllDepartments() {
return departmentDao.findAllDepartments();
}
#Override
public Department findByUid(Long uid) throws DataAccessException {
return departmentDao.findByUid(uid);
}
}
dao:
public interface DepartmentDAO {
public void delete(long uid);
public List<Department> findAllDepartments();
public Department findByUid(Long uid);
public void save(Department user);
public void update(Department user);
}
dao/impl:
#Repository
public class DepartmentDAOImplSf implements DepartmentDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void delete(long uid) {
Department department = (Department) sessionFactory.getCurrentSession()
.get(Department.class, uid);
sessionFactory.getCurrentSession().delete(department);
}
#Override
public void save(Department department) {
sessionFactory.getCurrentSession().save(department);
}
#Override
public void update(Department department) {
sessionFactory.getCurrentSession().saveOrUpdate(department);
}
#Override
public List<Department> findAllDepartments() {
List<Department> list = (List<Department>) sessionFactory
.getCurrentSession()
.createQuery("FROM Department").list();
return list;
}
#Override
public Department findByUid(Long uid) {
Department department = (Department) sessionFactory
.getCurrentSession().get(Department.class, uid);
return department;
}
}
I know that the order is: domain model -> controller-> service -> dao ->db, but why use a DepartmentBO? and why DepartmentBoImpl autowired DepartmentDao? Who of them act first? Something that i'm not understanding is messing up my conception of how it works and the sequence of the process..
Thanks for your help ;)
EDIT: "
In few words my question is, what is the sequence of this code? user goes on the /home page that redirect on "departments" page. But what happen before this --> "List list = departmentBO.findAllDepartments();" ?;)
When the departmentBO.findAllDepartments() method is called if you look at the code it invokes the sessionFactory. That is an internal factory class in Hibernate that basically builds a transactional connection to the DB in order to run a query. You are defining the query in the createQuery method and then ultimately executing it with the list() method. These two methods are part of the database session that Hibernate has instantiated.
Departments Page -> departmentBO.findAllDepartments() -> sessionFactory -> createQuery -> list()
Or in pseudo code-ish
Departments Page -> execute findAllDepartments method -> fetch / build a database connection -> define the query -> execute the query -> Return the list!
I am trying to use FullTextEntityManager (and Spring) but getting a 'Session is closed' exception. I am able to query fine the first time, but the 2nd time, the exception is thrown. Here's my config:
#Service
#Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public class SearchServiceImpl extends BaseService implements SearchService {
public List<StrainSearchResultsListItem> advancedSearch(Pageable page,String species) {
return searchRepository.advancedSearch(page, species);
}
Repo impl:
#Repository
#Transactional(readOnly = true)
public class SearchRepositoryImpl implements SearchRepository {
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
protected FullTextEntityManager getFullTextEntityManager() {
if (fullTextEntityManager == null) {
fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
}
return fullTextEntityManager;
}
As soon as I call fullTestQuery.getResultList() the second time, it hurls with a 'Session is closed' exception.
FullTextQuery fullTextQuery =
getFullTextEntityManager()
.createFullTextQuery(booleanQuery, Strain.class);
fullTextQuery.getResultList()
Any ideas are appreciated.
thanks
It might be that you forgot to enable TransactionManagement in your spring configuration file. #EnableTransactionManagement to a spring configuration file to enable transaction management.
Your entity class should be like this-
#Entity
#Table(name="keywordsentity")
#Indexed
#AnalyzerDef(
name="fulltext",
tokenizer=#TokenizerDef(factory=StandardTokenizerFactory.class),
filters={
#TokenFilterDef(factory=LowerCaseFilterFactory.class),
#TokenFilterDef(factory=SnowballPorterFilterFactory.class,
params={#Parameter(name="language", value="English") })
}
)
public class Keywordsentity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#JsonProperty
//index = Index.YES, analyze=Analyze.YES, store = Store.YES
#Field
#Analyzer(definition="fulltext")
private String keywordname;
And Your service class should be like this
#Service
public class KeywordService {
#PersistenceContext(type = PersistenceContextType.EXTENDED, name = "keywordPU")
private EntityManager em;
private FullTextEntityManager ftem;
public void updateFullTextIndex() throws Exception {
getFullTextEntityManager().createIndexer().startAndWait();
}
protected FullTextEntityManager getFullTextEntityManager() {
if (ftem == null) {
ftem = Search.getFullTextEntityManager(em);
}
return ftem;
}
#Transactional
public List<Keywordsentity> search(String summary, String description)
{
String searchString = summary.concat(" ").concat(description);
System.out.println("searchString-----------------------------"+searchString);
QueryBuilder qb = getFullTextEntityManager().getSearchFactory().buildQueryBuilder().forEntity(Keywordsentity.class).get();
//lucene query
org.apache.lucene.search.Query query = qb
.keyword()
.onField("keywordname").matching(searchString)
.createQuery();
Query fullTextQuery = getFullTextEntityManager().createFullTextQuery(query, Keywordsentity.class);
System.out.println("fullTextQuery------------------================="+fullTextQuery);
List<Keywordsentity> result = new ArrayList<Keywordsentity>();
try
{
result = fullTextQuery.getResultList();
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("size --------------------=========="+result.size());
for (Keywordsentity keywordone : result) {
System.out.println("keyword------------"+keywordone);
Map<String,String> team =new HashMap<String,String>();
Set<Teamsentity> teams= keywordone.getTeamsentity();
{
for(Teamsentity teamsentityone :teams )
{
String ids = String.valueOf(teamsentityone.getId());
team.put("id",ids);
team.put("name",teamsentityone.getName());
team.put("description",teamsentityone.getDescription());
}
System.out.println("teams =================="+teams);
}
}
return result;
}
}
Then Repository and controller should be normal way nothing else.
In dependency only one -
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.10.5.Final</version>
</dependency>