Mockito Predicate JPA not run correctly - unit-testing

In Unit Test Class:
#Mock
EntityManager entityManager;
#Mock
Root<RedFox> redFoxRoot;
#Mock
Expression expression;
#Mock
Path path;
#Mock
Predicate predicate;
#Test
public void filterTest(){
TypedQuery<RedFox> redFoxQuery = (TypedQuery<RedFox>) Mockito.mock(TypedQuery.class);
CriteriaQuery<RedFox> redFoxCriteriaQuery = Mockito.mock(CriteriaQuery.class);
Mockito.when(redFoxCriteriaQuery.where(Mockito.any(Predicate[].class)))
.thenReturn(redFoxQuery);
Mockito.when(redFoxCriteriaQuery.orderBy(Mockito.anyList())).thenReturn(redFoxCriteriaQuery);
CriteriaBuilder builder = Mockito.mock(CriteriaBuilder.class);
Mockito.when(redFoxRoot.get("isDeleted")).thenReturn(path);
Mockito.when(path.isNull()).thenReturn(predicate);
Mockito.when(builder.literal(Mockito.any())).thenReturn(expression);
Mockito.when(redFoxCriteriaQuery.from(RedFox.class)).thenReturn(redFoxRoot);
Mockito.when(entityManager.createQuery(redFoxCriteriaQuery)).thenReturn(redFoxQuery);
List<RedFox> redFoxs = new ArrayList<>();
RedFox redFox = new RedFox();
redFox.setTitle("abc");
redFox.setRedFoxStatus("");
redFox.setId(UUID.randomUUID());
redFoxs.add(redFox);
Mockito.when(redFoxQuery.getResultList()).thenReturn(redFoxs);
}
In class service:
public List<RedFox> filter(){
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<RedFox> redFoxCriteriaQuery = builder.createQuery(RedFox.class);
Root<RedFox> root = redFoxCriteriaQuery.from(RedFox.class);
redFoxCriteriaQuery.select(root);
List<Predicate> searchClause = new ArrayList<>();
searchClause.add(builder.isFalse(root.get("isDeleted")));//root cause error
Predicate[] searchClauses = searchClause.toArray(Predicate[]::new);
Query executingQuery = em.createQuery(redFoxCriteriaQuery.where(searchClauses)
.orderBy(orderBys));//Null pointer exception
List<RedFox> resultData = executingQuery
.getResultList();
..............................
}
My problem is when I comment the searchClause.add(builder.isFalse(root.get("isDeleted"))), it mean that the searchClauses is empty Array, then the code execute successfully.
But when the search clauses is not empty, then redFoxCriteriaQuery.where(searchClauses) not use the result I mocked but return null, and it will cause the null pointer exception.
I've been tucked 2 days but still don't know why so please help me with this issue.

Change
Mockito.when(redFoxCriteriaQuery.where(Mockito.any(Predicate[].class)))
.thenReturn(redFoxQuery);
to
Mockito.when(redFoxCriteriaQuery.where((Predicate[].class) Mockito.any()))
.thenReturn(redFoxQuery);
So, it can work with any non null object.
But if you write Mockito.any(Predicate[].class), then it just compare 2 array with type Predicate. And of course, 2 array cannot equal although all the elements in each array are equal.

Related

Criteria API in hibernate 5

I am migrating from Hibernate 3 to Hibernate 5 and have the following function
public static <T extends Saveable> T searchByNaturalKeys(T entity, Map<String, Object>
naturalKeysMap)
throws Exception{
// CriteriaQuery<?> criteria = null;
try {
Session session = getSession();
NaturalIdentifier naturalIdentifier = new NaturalIdentifier();
for (Entry<String, Object> entry : naturalKeysMap.entrySet()) {
naturalIdentifier.set(entry.getKey(), entry.getValue());
}
criteria = session.createCriteria(entity.getClass()).add(naturalIdentifier);
}
I tried to do the same thing for Hibernate 5 here is my approach
criteria = builder.createQuery(entity.getClass());
Root<?> root = criteria.from(entity.getClass());
criteria.where(builder.equals(naturalKeysMap));
List<?> categories = session.createQuery(criteri).getSingleResult();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<?> criteriaQuery = criteriaBuilder.createQuery(entity.getClass());
return (T) criteria.uniqueResult();
I know I am doing something wrong here. Can anybody give me right approach for this?
Another approach to do above thing is also welcomed

How to write unit test for spring cloud stream function based method?

When I try to test a spring cloud stream function based method, it always happens NullPointerException about InputDestination.
I have two questions:
It's hard for me to know how to write UT from the official doc. official test doc
Besides, how to write integration Test if test file has some dependencies. It seems create a new context and always has NoSuchBeanDefination error.
I have tried as flow, but the context can not find some dependency beans.
#Test
public void sampleTest() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(
MyTestConfiguration.class))
.run("--spring.cloud.function.definition=uppercase")) {
InputDestination source = context.getBean(InputDestination.class);
OutputDestination target = context.getBean(OutputDestination.class);
source.send(new GenericMessage<byte[]>("hello".getBytes()));
assertThat(target.receive().getPayload()).isEqualTo("HELLO".getBytes());
}
}
So I just want to write UT, but still have NPE.
Here is my code.
#Bean
public Function<Message<List<DemoBean>>, Message<DemoBean>> findFirstBean( ){
return message -> {
List<DemoBean> demoBeans = message.getPayload();
return MessageBuilder.withPayload(demoBeans.get( 0 )).build();
};
}
Here is my test.
#SpringBootTest
#ActiveProfiles(profiles = "local")
#Import({ TestChannelBinderConfiguration.class})
class FunctionDemoTest {
#Autowired
private InputDestination inputDestination;
#Autowired
private OutputDestination outputDestination;
private FunctionDemo functionDemo;
// some dependency need to mock
private DemoService demoService;
#BeforeEach
void setUp() {
demoService = Mockito.mock( DemoService.class );
functionDemo = new FunctionDemo( demoService);
}
#Test
public void findFirstBeanTest() {
DemoBean demoBean = new DemoBean();
demoBean.setName("Howard");
demoBean.setAge( 1 );
DemoBean demoBean1 = new DemoBean();
demoBean1.setName("Frank");
demoBean1.setAge( 2 );
List<DemoBean> demoBeanList = new ArrayList<>();
demoBeanList.add( demoBean );
demoBeanList.add( demoBean1 );
Message<List<DemoBean>> inputMessage = MessageBuilder.withPayload(demoBeanList).build();
inputDestination.send(inputMessage,"findFirstBean-in-0");
Assertions.assertNotNull( outputDestination.receive( 10000, "findFirstBean-out-0") );
}
}
Here is error:
java.lang.NullPointerException: while trying to invoke the method org.springframework.messaging.SubscribableChannel.send(org.springframework.messaging.Message) of a null object returned from org.springframework.cloud.stream.binder.test.InputDestination.getChannelByName(java.lang.String)
at org.springframework.cloud.stream.binder.test.InputDestination.send(InputDestination.java:89)
at com.successfactors.caf.listener.FunctionDemoTest.raePdrResultProcessor(FunctionDemoTest.java:82)
Well, I know the root cause of NPE.
Message<byte[]> receive(long timeout, String bindingName)
It seems should be destinationName instead of bindingName in source code.
Any other answers would be appreciated.

Junit error - No value present or no such element

testclass.java
#Test
public void testgetDictionaryValueListById() {
DictionaryValue dictionaryValue = new DictionaryValue();
dictionaryValue.setId(1);
dictionaryValue.setValueName("Test Dictionary Value");
dictionaryValue.setValueKey("12345678");
dictionaryValue.setStatus("Active");
dictionaryValue.setCreatedOn(new Date());
dictionaryValue.setUpdatedOn(new Date());
Mockito.when(dictionaryValueRepo.findById(1).get()).thenReturn(dictionaryValue);
assertThat(dictionaryService.getDictionaryValueListById(1)).isEqualTo(dictionaryValue);
}
Service.java
public DictionaryValue getDictionaryValueListById(int id) {
return dictionaryValueRepo.findById(id).get();
}
Repo.java
#Repository
public interface DictionaryValueRepo extends JpaRepository<DictionaryValue, Integer> {
}
I am getting no such value present again and again on executing test case in testclass.java. I don't know why? but when I am running my service method from the controller it is working as expected - fetching records from the database but not working in a test case.
Your test should be like this and please check out the naming. You need to Mock the step findId() befor the `get().
#InjectMocks
Service cut;
#Mock
DictionaryValueRepo dictionaryValueRepoMock;
// Can skipped by adding a #RunWith... on Testclass
#Before
public init() {
Mockito.initMocks(this);
}
#Test
public void testgetDictionaryValueListById() {
// Prepare Data
final int testId = 1;
DictionaryValue dictionaryValue = new DictionaryValue();
dictionaryValue.setId(testId);
dictionaryValue.setValueName("Test Dictionary Value");
dictionaryValue.setValueKey("12345678");
dictionaryValue.setStatus("Active");
dictionaryValue.setCreatedOn(new Date());
dictionaryValue.setUpdatedOn(new Date());
// config mocking
Mockito.when(dictionaryValueRepo.findById(testId)).thenReturn(<VALUE>);
Mockito.when(dictionaryValueRepo.findById(testId).get()).thenReturn(dictionaryValue);
// Call yout method for Testing
cut.getDictionaryValueListById(testId);
// verifies (if wanted) + assertions....
}
I concur with LenglBoy, so the right answer should be given to him.
The thing you need to be careful is what "VALUE" means in this line:
Mockito.when(dictionaryValueRepo.findById(testId)).thenReturn(VALUE);
The findById returns an Optional, so that is what you should build and pass to Mockito. Something like this:
Mockito.when(dictionaryValueRepo.findById(testId))
.thenReturn(Optional.ofNullable(dictionaryValue));
And for a scenario where the id does not exists in BD, passing Optional.empty() should be good enough.

Using Spock to test Spring JdbcTemplate

I have the following Java 8 DAO method that uses Spring JdbcTemplate to hit a database:
class MyAppDao {
#Inject
DataSource dataSource
public List<String> getFizzByBuzzIds(List<Integer> buzzIds) {
String sql = "SELECT * from buzzes WHERE buzz_id IN ( :buzzIds )";
NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
Map<String, Object> paramValues = new HashMap<>(1);
paramValues.put("buzzIds", buzzIds);
List<Buzz> buzzes = jdbcTemplate.query(sql,
paramValues, (rs, rowNum) -> {
return new Buzz(rs.getString("buzz_id"), rs.getString("buzz_key"),
rs.getString("buzz_external_id"));
}
);
List<String> fizzes = figureOutSomehow();
return fizzes;
}
}
I cannot change the dependencies injected into this method. The NamedParameterJdbcTemplate instance must be defined inside this method. The only thing I can mock (easily) is the dataSource.
I am trying (and I know, the method isn't written to be conducive to unit tests at all!) to write a Spock unit test for this, and just want to verify that when getFizzByBuzzIds is called, that jdbcTemplate.query is called (with any arguments).
My best attempt:
def 'getFizzByBuzzIds attempts to get case info from the DB'() {
given:
MyAppDao dao = Spy(MyAppDao, constructorArgs: [ dataSource ]) {
getJdbcTemplate() >> Mock(JdbcTemplate) {
1 * query('', null) // ???
}
}
when:
List<Integer> buzzIds = [1, 2, 3, 4]
dao.getFizzByBuzzIds(buzzIds)
then:
1 * dao.jdbcTemplate.query('', null) // ???
}
How can I configure the Spy and the then block label so that executing getFizzByBuzzIds verifies whether the underlying JdbcTemplate.query(...) method is called?

How to arrange and assert MustBeCalled for property setter in JustMock

I have a mocked class with a property that has a get and set. My code under test calls the setter to assign a connection string value. My test code mocks the class that contains the property and I add MustBeCalled when I arrange the mock.
ViewModel Code:
public class ClientViewModel
{
private readonly IMgmtDataProvider dataProvider;
public ClientViewModel(IMgmtDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
private string clientConnectionString;
public string ClientConnectionString
{
get { return clientConnectionString; }
set
{
clientConnectionString = value;
if (dataProvider != null)
dataProvider.ClientConnectionString = value;
}
}
}
Test Code:
//Arrange
const string connectionString = "THIS IS MY CONNECTIONSTRING";
var mockedDataProvider = Mock.Create<IMgmtDataProvider>();
Mock.Arrange(() => mockedDataProvider.ClientConnectionString).MustBeCalled();
//Act
var testViewModel = new ClientViewModel(mockedDataProvider);
testViewModel.ClientConnectionString = connectionString;
//Assert
var callCount = Mock.GetTimesCalled(() => mockedDataProvider.ClientConnectinString);
Assert.IsTrue(callCount > 0);
my Mock.Arrange(...).MustBeCalled(); appears to be applied to the getter, not the setter. So, when I call Mock.GetTimesCalled(...), it returns 0. I need to apply the MustBeCalled to the setter instead of the getter. I want to assure the dataprovider's connectionstring is getting set when the viewmodel's connection string gets set. How do I tell JustMock to track how many times a mocked setter is called?
Setters are arranged using the Mock.ArrangeSet() method, like so:
Mock.ArrangeSet(() => mockedDataProvider.ClientConnectionString = Arg.AnyString).MustBeCalled();
....
Mock.Assert(mockedDataProvider); // assert all expectations on this mock
You can also use Mock.AssertSet() as an alternative to the ArrangeSet().MustBeCalled() combo.
And finally, there's the Mock.GetTimesSetCalled() method for getting the number of times that a setter was called.
Check out the documentation on property mocking for examples.