LazyException in web service EJB - web-services

sorry for my bad english..
my model:
public class Dog {
private Integer id;
private String mame;
private List<Dog> childs; // lazy
}
my web service:
#WebService
public class DogWS {
#EJB
private DogRepository dogs
public Dog get(String id){
return dogs.get(id); // lazy exception
}
}
when i make and search with SOAPui tool.. i receive an Exception:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role
how to make and 'servlet filter' or similar in this case?

The problem is with accessing lazy collection after a dog object has been detached.
dogs.getChilds().size() method call before dog object was detached should solve the problem

Related

cannot stub ReactiveMongoRepository using Mockito.when

I'm new to reactive programming. I want to write some test cases for a reactive mongo repository. I tried to stub some query methods and use step-verifier to check the response, but my test gets fail .
ItemReactiveRepository.java
public interface ItemReactiveRepository extends ReactiveMongoRepository<Item, String> {
Mono<Item> findByDescription(String description);
}
Item.java
#Document
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Item {
#Id
private String id;
private String description;
private Double price;
}
ItemReactiveRepositoryTest.java
#DataMongoTest
#RunWith(SpringRunner.class)
public class ItemReactiveRepositoryTest {
#Autowired
private ItemReactiveRepository itemReactiveRepository;
#Test
public void findById() {
Item itemForTest = new Item("ABC", "Samsung TV", 405.0);
Mockito.when(itemReactiveRepository.findById("ABC")).thenReturn(Mono.just(itemForTest));
StepVerifier.create(itemReactiveRepository.findById("ABC"))
.expectSubscription()
.expectNextMatches(item -> item.getPrice() == 405.0)
.verifyComplete();
}
}
Error I receive when running test
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
you stub either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
inside when() you don't call method on mock but on some other object.
Are there any limitations to use stubbing when test reactive streams? Or any other standard mechanism to test above scenarios?
Instead of using #Autowired you have to prepare mock for Repository from import org.mockito.Mock;
#Mock
ItemReactiveRepository itemReactiveRepository;
As #Thomas has mentioned, you are not mocking instead using the actual MongoDB using DataMongoTest instead you have to get rid of this and just mock the methods and test your service layer. Autowired is expecting all default configuration and a bean which is prepared by the container for you to use which is not the case, you have to mock and use.
ItemReactiveRepository itemReactiveRepository=org.mockito.Mockito.mock(ItemReactiveRepository.class);
This worked for me.

Spring boot Unit test with #WebMvcTest - execution doesn't enter service layer from controller and returns null without error

I am writing unit test for a controller of my spring boot application.
I have typical MVC classes: ObjectSchemaController, ObjectSchemaService and ObjectSchemaDao.
I have written unit test with #WebMvcTest and mocked my service and dao class with #MockBean. (following this guide: https://www.baeldung.com/spring-boot-testing)
Below is my unit test :
#RunWith(SpringRunner.class)
#WebMvcTest(ObjectSchemaController.class)
public class ObjectSchemaControllerTest2 {
#Autowired
private MockMvc mvc;
#MockBean
private ObjectSchemaService service;
#MockBean
private ObjectSchemaDao dao;
#Autowired
ObjectMapper objectMapper;
#Test
public void testCreateObjectSchemaPass() throws Exception {
String payload = "{\"some_key\":\"some val\"}";
ObjectSchema objectSchema = objectMapper.readValue(payload, ObjectSchema.class);
Mockito.when(service.createSchema(objectSchema))
.thenReturn(objectSchema);
Mockito.when(dao.createSchema(objectSchema)).thenReturn(objectSchema);
mvc.perform(MockMvcRequestBuilders.post("/objectservice/schema/")
.contentType("application/json")
.content(objectMapper.writeValueAsString(objectSchema)))
.andExpect(status().isOk());
}
}
below is my service class:
#Service
public class ObjectSchemaService {
#Autowired
ObjectSchemaDao objectSchemaDao;
public ObjectSchema createSchema(#Valid ObjectSchema objectSchema)throws Exception {
return objectSchemaDao.createSchema(objectSchema);
}
}
The issue I am facing with Unit test is, the service layer doesn't get executed and returns null value.
When I debug, I can see execution reaching in my controller class and ObjectSchemaService as being mockito-mocked in the controller. But the execution never goes in service layer and the value returned by service method is null.
I have referenced other guides- they are doing similar steps. But its not working for me. What am I missing here?
I have also seen this post with similar issue.
Unit Test POST with #WebMvcTest - #MockBean Service returns null
I made sure the input objects to both my actual controller and the one I am passing in unit case are instances of same class.
You are mocking the ObjectSchemaService but no behaviour is expected.
You need to setup the behaviour for the services that are mocked. So depending on the method signature and result somethink like.
Mockito.when(service.createSchema(Mockito.any(ObjectSchema.class)).thenReturn(objectSchema);
At the moment the ObjectSchemaService mock just returns a default value which is null in your case.
In order to be transparent and unobtrusive all Mockito mocks by default return 'nice' values. For example: zeros, falseys, empty collections or nulls.
If you update your answer with details for ObjectSchemaService I could also update my answer.
You mock ObjectSchemaService so you need to tell the service how mock the values from the service when a method is called. If you don't mock the values of the service Mockito don't know what they have to return always give you null. Not need to mock ObjectSchemaDao in this test.
Note: I use Lombok in the code as ObjectSchema.builder() to return the object with the Id when is stored in the database, you can use a constructor. Assuming the service return the object.
The code looks like this:
import static org.mockito.BDDMockito.given;
#Test
public void testCreateObjectSchemaPass() throws Exception {
String payload = "{\"some_key\":\"some val\"}";
ObjectSchema objectSchema = objectMapper.readValue(payload, ObjectSchema.class);
given(service.createSchema(objectSchema)).willReturn(
ObjectSchema.builder()
.id(1)
.someKey("Some Val")
.build());
mvc.perform(MockMvcRequestBuilders.post("/objectservice/schema/").contentType("application/json").content(objectMapper.writeValueAsString(objectSchema)))
.andExpect(status().isOk());
}

Mocking EntityManager (Mockito)

I have the following code in one of my classes:
#PersistenceContext
protected EntityManager entityManager;
public entryPoint() {
for(Animal:getTheAnimals()) {
System.out.println(Animal.getName());
}
}
private List<Animal> getTheAnimals() {
return List<Animal>entityManager.createNamedQuery("myQuery").setParameter("myParam", new Date()).getResultList();
}
In my test class I have the following:
#Mock
private EntityManager entityManager;
#Mock
private Query query;
#Autowired
private ClassToTest classToTest;
#Test
public void someTest() {
List<Animal> list = new ArrayList<Animal>();
Mockito.when(entityManager.createNamdeQuery("myQuery")).thenReturn(query);
Mockito.when(query.setParameter(any(String.class), any(java.util.Date.class)).getResultList()).thenReturn(list);
...something more here...
}
As you can see the expected behavior is that the empty list is returned, and zero animal names get printed. However that is not the case and the actual animals from the db are being returned in the list. What am I missing? I tried several variations of this with the same result.
Thanks for reading.
In your question, you use #Autowired directly on the field for the system under test, which seems to instruct Spring to resolve the dependencies. It likely does so from your actual (production) configuration.
By comparison, a common Mockito annotation is #InjectMocks, which ignores Spring, instantiates the object using as many #Mock objects as possible.
Related SO question: Injecting into #Autowired variable during testing

What's the lazy strategy and how does it work?

I have a problem. I'm learning JPA. I'm using embedded OpenEJB container in unit tests, but only working is #OneToMany(fetch=EAGER). Otherwise is the collection allways null. I haven't found, how the lazy strategy works, how the container fills the data and in which circumstances triggers the container the loading action?
I have read, that the action triggers when the getter is being called. But when I have the code:
#OneToMany(fetch = LAZY, mappedBy="someField")
private Set<AnotherEntities> entities = new Set<AnotherEntities>();
...
public Set<AnotherEntities> getEntities() {
return entities;
}
I'm always getting null. I thing, the LAZY strategy cannot be tested with embedded container. The problem might be also in the bidirectional relation.
Does have anybody else similar expiriences with the JPA testing?
Attachments
The real test case with setup:
#RunWith(UnitilsJUnit4TestClassRunner.class)
#DataSet("dataSource.xml")
public class UnitilsCheck extends UnitilsJUnit4 {
private Persister prs;
public UnitilsCheck() {
Throwable err = null;
try {
Class.forName("org.hsqldb.jdbcDriver").newInstance();
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
props.put("ds", "new://Resource?type=DataSource");
props.put("ds.JdbcDriver", "org.hsqldb.jdbcDriver");
props.put("ds.JdbcUrl", "jdbc:hsqldb:mem:PhoneBookDB");
props.put("ds.UserName", "sa");
props.put("ds.Password", "");
props.put("ds.JtaManaged", "true");
Context context = new InitialContext(props);
prs = (Persister) context.lookup("PersisterImplRemote");
}
catch (Throwable e) {
e.printStackTrace();
err = e;
}
TestCase.assertNull(err);
}
#Test
public void obtainNickNamesLazily() {
TestCase.assertNotNull(prs);
PersistableObject po = prs.findByPrimaryKey("Ferenc");
TestCase.assertNotNull(po);
Collection<NickNames> nicks = po.getNickNames();
TestCase.assertNotNull(nicks);
TestCase.assertEquals("[Nick name: Kutyafája, belongs to Ferenc]", nicks.toString());
}
}
The bean Presister is the bean mediating access to the entity beans. The crucial code of class follows:
#PersistenceUnit(unitName="PhonePU")
protected EntityManagerFactory emf;
public PhoneBook findByPrimaryKey(String name) {
EntityManager em = emf.createEntityManager();
PhoneBook phonebook = (PhoneBook)em.find(PhoneBook.class, name);
em.close();
return phonebook;
}
Entity PhoneBook is one line of phone book (also person). One person can have zero or more nick names. With EAGER strategy it works. With LAZY the collection is allways null. May be the problem is in the detaching of objects. (See OpenEJB - JPA Concepts, part Caches and detaching.) But in the manual is written, that the collection can be sometimes (more like manytimes) empty, but not null.
The problem is in the life cycle of an entity. (Geronimo uses OpenJPA, so le't see OpenJPA tutorial, part Entity Lifecycle Management.) The application uses container managed transactions. Each method call on the bean Persiser runs in an own transation. And the persistency context depends on the transaction. The entity is disconnected from its context at the end of the transaction, thus at the end of the method. I tried to get the entity and on second line in the same method to get the collection of nick names and it worked. So the problem was identifyed: I cannot get additionally any entity data from the data store without re-attaching the entity to some persistency context. The entity is re-attached by the EntityManager.merge() method.
The code needs more correctures. Because the entity cannot obtain the EntityManager reference and re-attach itself, the method returning nick names must be moved to the Persister class. (The comment Heureka marks the critical line re-attaching the entity.)
public Collection<NickNames> getNickNamesFor(PhoneBook pb) {
//emf is an EntityManagerFactory reference
EntityManager em = emf.createEntityManager();
PhoneBook pb = em.merge(pb); //Heureka!
Collection<NickNames> nicks = pb.getNickNames();
em.close();
return nicks;
}
The collection is then obtained in this way:
//I have a PhoneBook instance pb
//pb.getNickNames() returns null only
//I have a Persister instance pe
nicks = pe.getNickNames(pb);
That's all.
You can have a look at my second question concerning this topic I'have asked on this forum. It is the qustion OpenJPA - lazy fetching does not work.
How I would write the code
#Entity
public class MyEntity {
#OneToMany(fetch = LAZY, mappedBy="someField")
private Set<AnotherEntities> entities;
// Constructor for JPA
// Fields aren't initalized here so that each em.load
// won't create unnecessary objects
private MyEntity() {}
// Factory method for the rest
// Have field initialization with default values here
public static MyEntity create() {
MyEntity e = new MyEntity();
e.entities = new Set<AnotherEntities>();
return e;
}
public Set<AnotherEntities> getEntities() {
return entities;
}
}
Idea no 2:
I just thought that the order of operations in EAGER and LAZY fetching may differ i.e. EAGER fetching may
Declare field entities
Fetch value for entities (I'd assume null)
Set value of entities to new Set<T>()
while LAZY may
Declare field `entities
set value of entities to new Set<T>()
Fetch value for entities (I'd assume null)'
Have to find a citation for this as well.
Idea no 1: (Not the right answer)
What if you'd annotate the getter instead of the field? This should instruct JPA to use getters and setters instead of field access.
In the Java Persistence API, an entity can have field-based or
property-based access. In field-based access, the persistence provider
accesses the state of the entity directly through its instance
variables. In property-based access, the persistence provider uses
JavaBeans-style get/set accessor methods to access the entity's
persistent properties.
From The Java Persistence API - A Simpler Programming Model for Entity Persistence

Moq custom IIdentity

I created a custom RoleProvider (standard webforms, no mvc) and I would like to test it. The provider itself integrates with a custom implementation of IIdentity (with some added properties).
I have this at the moment:
var user = new Mock<IPrincipal>();
var identity = new Mock<CustomIdentity>();
user.Setup(ctx => ctx.Identity).Returns(identity.Object);
identity.SetupGet(id => id.IsAuthenticated).Returns(true);
identity.SetupGet(id => id.LoginName).Returns("test");
// IsAuthenticated is the implementation of the IIdentity interface and LoginName
However when I run this test in VS2008 then I get the following error message:
Invalid setup on a non-overridable member: id => id.IsAuthenticated
Why is this happening? And most important, what do I need to do to solve it?
Grz, Kris.
You should mock IIdentity (instead of CustomIdentity - only possible if the variables you are mocking are declared in the interface) or declare the used variables as virtual.
To mark as virtual, do this: In your concrete class CustomIdentity, use
public virtual bool isAuthenticated { get; set; }
instead of
public bool isAuthenticated { get; set; }
Moq and other free mocking frameworks doesn't let you mock members and methods of concrete class types, unless they are marked virtual.
Finally, you could create the mock yourself manually. You could inherit CustomIdentity to a test class, which would return the values as you wanted. Something like:
internal class CustomIdentityTestClass : CustomIdentity
{
public new bool isAuthenticated
{
get
{
return true;
}
}
public new string LoginName
{
get
{
return "test";
}
}
}
This class would be only used in testing, as a mock for your CustomIdentity.
--EDIT
Answer to question in comments.
Are you mocking against the interface IIdentity, or mocking against your custom type?
Without having a fuller code snippet to look at, I am guessing that it is complaining that the IsAuthenticated is not marked as virtual in your custom implementation. However, this could only be the case if you were mocking against the concrete type, not the interface.