Junit for Solr Indexing Documents from AEM - junit

I have my ServiveImpl class, which has public methods to create and delete index from AEM to Solr. How can we handle the Junit for these void methods using Mockito? Any pointers will be help. Mainly for testing integration with Solr

In this case, your JUnit wouldn't really make any difference other than giving you some test coverage.
The reason behind writing a Junit is to ensure that a method returns a result, or throws an exception. With a void method, the only thing that can be tested is that the method executes.
To solve this, it would be good to at least return a boolean value. Without this, you can never be sure whether the index was really deleted or not.
So the suggestion here would be-
Update the method to ensure the correct error handling takes place.
Based on the method execution, return a boolean value at least. This will not have any impact on your project because the method was void anyway and no calls would be impacted.
In your Junit, assert the returned value as true or false, or just use the assertTrue method.
boolean deleteIndex(String indexName) {
if (deleted) {
return true;
} else {
return false;
}
}
JUnit-
#InjectMocks
private ServiveImpl service = new ServiveImpl();
#Test
public void testIndexDeletion() {
boolean indexDeleted = ServiveImpl.deleteIndex("someIndex");
assertTrue(indexDeleted);
}

Related

How to skip static validation in JUnit test with Mockito

I have a function I need to test:
#Override
public ResponseEntity<BasicResponse> myFunction(HttpServletRequest request, #RequestBody Dto dto, BindingResult result) {
try {
ValidationUtils.invokeValidator(validator, dto, result);
if (result.hasErrors()) {
// do things
} else {
//do things
}
} catch (Exception e) {
// catch
}
//return things;
}
But when I test the function it always go to the catch because of the validator, it says:
"Validator does not support Dto".
I don't care about the validation, I need to test what's inside the try, so I try to use doNothing to skip the validation but I get an error because it's void:
#Test
void TestMyFunction() {
doNothing().when(ValidationUtils.invokeValidator(validator, dto, result));
ResponseEntity<BasicResponse> response = controller.myFunction(request, dto, result);
// assert something
}
Any idea on how to proceed? I can't change the function, I can only write the test and I'm new at this. Thank you.
If ValidationUtils was an object instance that is a Mockito spy or mock, you would be able to mock it like so:
doNothing()
.when(validationUtils)
.invokeValidator(validator, dto, result);
This, unfortunately, does not seem to be the case in your test - ValidationUtils seems to be a class on which a static method is called, which Mockito can handle since version 3.4.0 (before that it was usually handled by PowerMock). thenAnswer should be used with the mockedStatic object instance, similarly to this answer, since the method's return type is void.
An important additional (but mandatory) note: mocking static methods is discouraged and should be avoided whenever possible. It slows down the tests and is a sign of bad design of the classes. The validator should be injected into the class or created using a factory, thanks to that a mocked object instance could be easily used.
I've checked that and in fact the thenAnswer part is not required to do nothing after using mockStatic on a class.
try (var mockedStatic = Mockito.mockStatic(ValidationUtils.class)) {
// test code
}
The code above makes ValidationUtils do nothing and return default values (0, false, null).
See this example (all tests pass).

Invalid Use Of Matchers Exception with toString() [duplicate]

I have this TestNG test method code:
#InjectMocks
private FilmeService filmeService = new FilmeServiceImpl();
#Mock
private FilmeDAO filmeDao;
#BeforeMethod(alwaysRun=true)
public void injectDao() {
MockitoAnnotations.initMocks(this);
}
//... another tests here
#Test
public void getRandomEnqueteFilmes() {
#SuppressWarnings("unchecked")
List<Filme> listaFilmes = mock(List.class);
when(listaFilmes.get(anyInt())).thenReturn(any(Filme.class));
when(filmeDao.listAll()).thenReturn(listaFilmes);
List<Filme> filmes = filmeService.getRandomEnqueteFilmes();
assertNotNull(filmes, "Lista de filmes retornou vazia");
assertEquals(filmes.size(), 2, "Lista não retornou com 2 filmes");
}
And I'm getting a "org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:" in the call of listAll() method in this code:
#Override
public List<Filme> getRandomEnqueteFilmes() {
int indice1, indice2 = 0;
List<Filme> filmesExibir = new ArrayList<Filme>();
List<Filme> filmes = dao.listAll();
Random randomGenerator = new Random();
indice1 = randomGenerator.nextInt(5);
do {
indice2 = randomGenerator.nextInt(5);
} while(indice1 == indice2);
filmesExibir.add(filmes.get(indice1));
filmesExibir.add(filmes.get(indice2));
return filmesExibir;
}
I'm prety sure I'm missing something here but I don't know what it is! Someone help?
when(listaFilmes.get(anyInt())).thenReturn(any(Filme.class));
There's your problem. You can't use any in a return value. any is a Matcher—it's used to match parameter values for stubbing and verification—and doesn't make sense in defining a return value for a call. You'll need to explicitly return a Filme instance, or leave it null (which is the default behavior, which would defeat the point of stubbing).
I should note that it's often a good idea to use a real List instead of a mock List. Unlike custom code you've developed, List implementations are well-defined and well-tested, and unlike mock Lists a real List is very unlikely to break if you refactor your system under test to call different methods. It's a matter of style and testing philosophy, but you may find it advantageous just to use a real List here.
Why would the above rule cause that exception? Well, this explanation breaks some of Mockito's abstractions, but matchers don't behave like you think they might—they record a value onto a secret ThreadLocal stack of ArgumentMatcher objects and return null or some other dummy value, and in the call to when or verify Mockito sees a non-empty stack and knows to use those Matchers in preference to actual argument values. As far as Mockito and the Java evaluation order are concerned, your code looks like the following:
when(listaFilmes.get(anyInt())).thenReturn(null);
when(filmeDao.listAll(any())).thenReturn(listaFilmes); // nonsense
Naturally Mockito sees an any matcher, and listAll doesn't take an argument, so there are 0 matchers expected, 1 recorded.

How To write test method for ResultSetExtractor using mockito?

How to write a method in myDAOTest class to test my DAOImpl Class using Mockito? here is the method which i need to test from my TestClass.
#Override
public myCustomResponse mymethod(String query, Map<String, Object> parameters) {
jdbcTemplate.query(query, parameters, new ResultSetExtractor<List<MyObject>>() {
#Override
public List<MyObject> extractData(ResultSet result) throws SQLException, DataAccessException {
try {
List<MyObject> myObject= new ArrayList<>();
while (result.next()) {
response = getResponseDetails(result);
}
return myObject;
} catch (SQLException sqlException) {
LOG.debug(MyConstants.DATABASE_EXCEPTION_MESSAGE);
throw new MyCustomeException(MyConstants.DATABASE_EXCEPTION_MESSAGE);
}
}
});
}
return response;
}
Possibility 1:
Extract your ResultSetExtractor into it's own class, which makes it much simpler to test than as an anonymous inner class.
Possibility 2:
Mock the jdbcTemplate, create an ArgumentCaptor, call the method and then do...
Mockito.verify(this.jdbcTemplate).query(any(), any(), captor.capture());
This allows you to then get the ResultSetExtractor from the ArgumentCaptor and run tests on that. But this makes your whole test complex, so I still suggest possibility 1.
Possibility 3:
Test the whole thing against an in-memory database,testing the ResultSetExtractor only indirectly. Since this seems to be Spring, there are easy ways to do so, but of course, your unit test will now include a whole SpringApplicationContext, a db, etc. - which makes it slower than a "pure" unit test with only mocks. Since it's something that fires queries to a db, you will need to run it against a db anyway some time, otherwise your tests will not really be complete (simulating it via mocks is good for the basics, but not the same thing).

JUnit: should I do null-checks after assertNotNull

Should I do null-checks after assertNotNull to avoid null-pointers in test code? E.g.
assertNotNull(foo);
if (foo != null) {
assertNotNull(foo.getBar());
}
Or just
assertNotNull(foo);
assertNotNull(foo.getBar());
You are doing right with...
assertNotNull(foo);
assertNotNull(foo.getBar());
You don't need to set another condition to check the same if you previously did it.
Using assertX methods ensure the condition is actually asserted. So, by using assertNotNull you ensure that something is not null.
The correct way is as you showed:
assertNotNull(foo);
assertNotNull(foo.getBar());
If you start digging deeper into the assertNotNull method, you will see this calls:
// First call
static public void assertNotNull(Object object) {
assertNotNull(null, object);
}
// Second call
static public void assertNotNull(String message, Object object) {
assertTrue(message, object != null);
}
// Third call
static public void assertTrue(String message, boolean condition) {
if (!condition) {
fail(message);
}
}
Quoting the assertTrue documentation:
Asserts that a condition is true. If it isn't it throws an AssertionError with the given message.
Conclusion, you don't have to do null checks after asserting for not null values since junit is taking care of that for you
You even don't need to have the first null check. The test will fail with a NullPointerException if foo is null. It is a matter of taste whether to have the null check or not.

Suppress JOptionPane.showInputDialog in junit test

I am using the JOptionPane.showInputDialog call in my code.
When the junit tests run it pops up the window.
Is there a way to suppress the pop-up?
Wold mocking it help?
Please help me on this.
I know - this question is ancient. But maybe sometimes someone will have the same problem...
Remember: It's your code, isn't it? So you can easily refactor from
public boolean myMethod() {
String value = "NOTHING";
if(this.someCondition) {
value = JOptionPane.showInputDialog(...);
}
return "NOTHING".equals(value);
}
to
public boolean myMethod() {
String value = "NOTHING";
if(this.someCondition) {
value = getValueFromDialog();
}
return "NOTHING".equals(value);
}
protected getValueFromDialog() {
return JOptionPane.showInputDialog(...)
}
This done, you can write a test mocking away the actual invocation of JOptionPane (Example uses Mockito syntax)
#Test
public void test_myMethod() {
MyClass toTest = mock(MyClass.class);
//Call real method we want to test
when(toTest.myMethod()).doCallRealMethod();
//Mock away JOptionPane
when(toTest.getValueFromDialog()).thenReturn("HELLO JUNIT");
//Perform actual test code
assertFalse(toTest.myMethod());
}
All done - now add tests simulating all the funny stuff that might happen as a result of JOptionPane.showInputDialog() (returning null, returning unexpected values...) by simply adding test cases and different values for
when(toTest.getValueFromDialog()).thenReturn(...);