Testing a private method in unit testing - java

I know the answer to this question is: you do not test private method but only the public method that will eventually lead to that private method invocation.
BUT
In my case, the public method actually starting up a consumer/connection to kafka, so i only want to test the logic done when a kafka message is received.
I do not want to make the logic method public as no one will use it out side of the kafka infrastructure, but still i want to unit test the logic done there.
What is the best practice solution? I can change the code if need be
Heres some examples:
the private method in question
private void handleConsumerRecord(ConsumerRecord<PK, byte[]> cr, Acknowledgment acknowledgment) throws IOException {
//logic to be tested
}
the private method that calls the private logic method
/**
* Initialize the kafka message listener
*/
private void initConsumerMessageListenerContainer(ProducerFactory<PK, V> producerFactory) {
if (!processAsBatch) {
// start a acknowledge message listener to allow the manual commit
acknowledgingMessageListener = (cr, acknowledgment) -> {
try {
handleConsumerRecord(cr, acknowledgment);
} catch (IOException e) {
log.error("Failed to handle consumed message, commiting message and performing irrecoverableException actions");
exceptionHandlerManager.getIrrecoverableExceptionHandler().performAction(null, cr.value(), cr.topic(), cr.key());
}
};
// start and initialize the consumer container
container = initContainer(acknowledgingMessageListener, producerFactory);
}
and this is the public method that starts everything
/**
* Start the message consumer
* The record event will be delegate on the onMessage()
*/
public void start(ProducerFactory<PK, V> producerFactory) {
initConsumerMessageListenerContainer(producerFactory);
container.start();
}
The unit test i tried to write
kafkaByteArrConsumer.getAcknowledgingMessageListener().onMessage(record, acknowledgment);
doThrow(TemporaryException.class).when(kafkaByteArrConsumer).getConsumerMessageLogic().onMessage(record.value(), acknowledgment);
Mockito.verify(exceptionHandlerManager.getTemporaryExceptionHandler(), Mockito.times(1))
.performAction();
As you can see, the getAcknowledgingMessageListener will not be initialized by the initConsumerMessageListenerContainer() and therefore i wont be able to access the handleConsumer method when mocking .getConsumerMessageLogic().onMessage
(which is called by the //some logic to be tested part)

A good compromise would be to change your method to protected or even to package-private, and then have your unit test located in the same package. The unit-test class doesn't have to reside under the same root. Say your source resides under "source" folder and tests reside under "test" folder. Just have the testing class reside in the same package. A very detailed answer could be found in this question: How can we test package-private class?
. Your question may be a duplicate of that question

Well, there are people who use PowerMock to test private methods etc. but I always recommend to avoid that. Maybe you should consider change your logic a little there or even better consider Kafka MockConsumer etc.

Related

Is it possible to bypass certain exception in unit test?

Is it even possible to bypass certain exceptions in mockito? This sounds crazy. You want to catch expected exceptions in the unit testing I assume. However I decided to give a try asking this question. Here is my scenario hope I could improve my understanding on mockito and general unit test principals via this.
I have to build a simple unit test for a particular class Foo in an enterprise web application using mockito unit test framework.
This Foo class requires ldap and database connections however due to a reason, I can not use development environment specific ldap and database in the unit test.
I just need to test part accessing ldap so that I decided to use unboundid in memory ldap which allows to create light weight directory at run time and remove it from memory after testing is done.
My question is during the instantiation of Foo class via #InjectedMocks annotation, it triggers chain reaction of calling many other classes and their methods. It threw many exceptions which I expected.
I am trying to find a way to somehow ignore some specific exceptions such as loading/reading environment specific properties files or database access and etc.
For my goal, I don't need reading prop files nor database access.
I read upon ExpectedException junit provides which is subset of mockito if I am not mistaken however I don't think its aim aligns with my intention of bypassing some of the exceptions. I could be wrong on this.
All I want to accomplish is:
Instantiate Foo class
Call one of its methods that would read a list of group from In memory ldap
Verify returned data
Here is water downed version of test class:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
private static InMemoryDirectoryServer ldapServer;
private static Integer ldapPort = xxxxx;
#InjectedMocks
Foo footester = Foo.getInstance();
#BeforeClass
public static void setUpBeforeClass() {
try {
// execute instantiate in memory ldap..
} catch (Exception e) {
// do print out
}
}
#Test
public void testLdap() {
// before it reaches here exceptions were thrown
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
// do tear down execution
}
}
You can catch an exception like this:
#Test(expected = YourExceptionHere.class)
public void testSomething()
{
foo(FOO_VALUE);
}

Specific setup for each junit test

I have a sequence of tests which have to be fed an input data in the form of a file.However,the exact data content to be fed into each would be specific.
I intend to use temporary files to achieve this.
The Setup method does not take a parameter.
SO ,what could be done so that the setup can be made to read a specific fragment for each specific test.
The actual set of steps in Setup would be same - creating a temporary file,but with a specific tailored piece of data.
Setup methods (i.e., methods annotated with #Before) are designed for running the same steps before every test case. If this isn't the behavior you need, just don't use them.
At the end of the day, a JUnit test is just Java - you could just have a method that takes a parameter and sets up the test accordingly and call it explicitly with the different arguments you need:
public class MyTest {
private void init(String fileName) {
// Reads data from the file and sets up the test
}
#Test
public testSomething() {
init("/path/to/some/file");
// Perform the test and assert the result
}
#Test
public testSomethingElse() {
init("/path/to/another/file");
// Perform the test and assert the result
}
}

How to cover close method in unit tests for autocloseable beans closed by spring

I have several Spring beans/components implementing AutoCloseable, and I expect the Spring Container to close them when the application context is destroyed.
Anyway, my code coverage tool is complaining because the close() methods are "uncovered by tests" from its point of view.
What should I do:
Introduce some trivial close() tests?
Just let it go and accept they will lower the coverage %
Something else?
You're not testing that the app closes the bean, you're testing that the bean closes properly when closed. If the implementation is non-trivial, then you should write a test for that behaviour. If all your method does is call close on a single field then don't bother testing it. However, if your close method calls close on multiple fields or does something a bit more complicated then you should test it.
For instance, given the following Closer class that must close all its Readers when it is closed...
public class Closer implements AutoCloseable {
private Reader[] readers;
public Closer(Reader... readers) {
this.readers = readers;
}
#Override
public void close() {
try {
for (Reader reader : readers) {
reader.close();
}
} catch (IOException ex) {
// ignore
}
}
}
You may wish to test as such:
public class CloserTest {
#Test
public void allReadersClosedWhenOneReaderThrowsException() {
// given
Reader badReader = mock(Reader.class);
Reader secondReader = mock(Reader.class);
doThrow(new IOException()).when(badReader).close();
Closer closer = new Closer(badReader, secondReader);
// when
closer.close();
// then
verify(badReader).close();
verify(secondReader).close(); // fails as loop stops on first exception
}
}
Excessively high code coverage can be a bad thing if it means that your unit tests contain large amounts of trivial tests, especially if those tests are fragile. They will increase the amount of effort required to maintain the unit tests, without actually adding anything.

For Junit issue: when test multiple thread

I use JDK ScheduledThreadPoolExecutor to do schdule job. I give simple code as below.
class Job implements Callable<Void>{
public Long id;
#Override
public Void call() throws Exception {
if (!isOk(id)) {
return null;
}
_context.exe(id);
return null;
}
void setId(Long id) {
this.id = id;
}
}
Every time i add this job to schedule service:
public void schedule() {
Job job = new Job();
job.setId(1L);;
_scheduledExecutor.schedule(job, 1000, TimeUnit.MILLISECONDS) ;
}
this job will delay call context's exe method.
My Question: I want assert _context's exe method called or not? How can I do this?
What I do currently, I try to add log in call() method and verify UT by my eyes.
PS: For this UT, I also try to mock _context's exe method, but job run in other thread, So I cannot assert it in currently thread. anyone have idea to help me write assert for this case?
Currently I do below way, but I still think there better solution for this, Just I don't known.
_context is instance of Context, I extend from this class.
public class UTContext extends Context {
public UTTestCase utTestCase ;
#Override
public void exe(Long id) {
utTestCase.setIsCall(true);
}
public void setUtTestCase(UTTestCase utTestCase) {
this.utTestCase = utTestCase;
}
}
Then I will assert isCall var in UT.
Is any one have good idea for this , pls give me answer. Thank you very much.
You are testing a piece of the middle of the call hierarchy, namely the thread creator/dispatcher code. That means you have to drive the code from the top and test either from the top or the bottom. There are several patterns for how you do that.
Either you instrument the bottom (exe(id)) or you measure from the top. With the scheduling delay, measuring from the top becomes very difficult.
Does exe() have side effects? Is that side effect testable from your test code? Can you infer the operation of one invocation of exe()? Can you infer the invocation of more than one? If the answer to any of these is "no", then you will have to go further.
#RamonBoza has provided a good solution.
You could also create a testable version of class Job, thus:
class JobUT extends Job {
#Override
public Void call() throws Exception {
Void result = super.call();
// Report error if wrong return result
}
}
(I know there are problems with the above code as Void is not being handled properly. I'm not in a position to refactor your code.)
You may also achieve the same objective using Aspect Oriented Programming, where you intercept the call after it has completed and perform the same testing.
For asserting on multithreading I usually create 'N' threads, and assign a different value to set for each thread.
Then join them all and at the end just check if the data of each thread is ¿stored? for example.
Imagine, you create 1000 threads that stores an integer to a database, so after those 1000 threads has finished you have to check if in the database all the data is stored.
A more hard kind of test is for integration test and shall be perform with different scenarios and middleware (OpenNebula, Amazon cloud, etc).
After server day, I know how to verify it now. I attached other question for reference:
Assert times of expectLastCall
Service service = EasyMock.createMock(Service.class);
service.applyInitialDump(entities);
EasyMock.expectLastCall().times(100);
processor.processInitialDump(entities)
EasyMock.verify(service);

Appropriate method encapsulation for unit testing

My class contains 14 private methods and 1 public method. The public method calls all the private method directly or indirectly via other private methods.
The public method also has a call to a DAO that queries the database.
I wrote a unit test for the class. Since you can't write unit test for private methods, I changed all the private methods to default access and wrote unit test for them.
I was told that I shouldn't change the encapsulation just for the purpose of testing. But my public method has a call to the DAO and gets its data from the call. Even if I were to write a test for the public method, I'm assuming it would be really long and complicated.
How should I approach this problem. On one hand, I have to write a really complicated test for the public method which accesses a DAO and on the other hand, change the access level of the methods and write short, simple test methods for them. What should I do?
Any suggestions will be greatly appreciated
Purists will tell you that the private methods could be extracted to another helper class providing accessible methods, and they could be right.
But if it makes sense to keep these utility methods inside the class, if the class is not part of a public API and is not intended to be subclassed (it could be final, for example), I don't see any problem with making some of its private methods package-protected or protected. Especially if this non-private visibility is documented, for example with the Guava annotation #VisibleForTesting.
Seems like you have two problems here:
How to test private methods (assuming in Java):
I would look at this question: How do I test a class that has private methods, fields or inner classes?
I personally like Trumpi's response:
The best way to test a private method is via another public method. If this cannot be done, then one of the following conditions is true:
The private method is dead code
There is a design smell near the class that you are testing
The method that you are trying to test should not be private
How to break the dependency of the DAO
You could try to use Dependency Injection to get rid of your dependency on the DAO. Then you can mock out the DAO and inject it into your test case.
The benefit is it truly becomes a unit test and not an integration test.
If it's complicated, it's probably because your class have more than one responsability. Normally, when you have private methods that do different things, is that you could have different classes with public methods that do that for you. Your class will become more easy to read, to test, and you will separate responsability. 14 private methods normally indicates this kind of thing :P
For example, you could have something like
public class LeFooService {
private final OtherServiceForConversion barService;
private final FooDao fooDao;
public LeeFooService(FooDao dao, OtherServiceForConversion barService) {
this.barService = barService;
this.fooDao = dao;
}
public void createAsFoo(Bar bar) throws ConversionException {
Foo foo = convert(bar);
fooDao.create(foo);
}
private Foo convert(Bar bar) {
// lots of conversion stuff, services calling D:
}
}
for testing correctly, you will have to test if conversion was done correctly. Because it's private, you will have to capture the foo sent to FooDao and see if all fields were set correctly. You can use argThat to capture what's sent to fooDao to test the conversion then. Your test would look something like
....
#Test
public void shouldHaveConvertedFooCorrectly() {
// given
Bar bar = mock(Bar.class);
// when
fooService.createAsFoo(bar);
// then
verify(fooDao).create(argThat(fooIsConvertedCorrectly());
}
private ArgumentMatcher<Foo> fooIsConvertedCorrectly() {
return new ArgumentMatcher<Foo>() { /*test stuff*/ };
}
....
But, if you separated the conversion to another class, like this:
public class LeFooService {
private final BarToFooConverter bar2FooConverter;
private final FooDao fooDao;
public LeeFooService(FooDao dao, BarToFooConverter bar2FooConverter) {
this.bar2FooConverter = bar2FooConverter;
this.fooDao = dao;
}
public void createAsFoo(Bar bar) throws ConversionException {
Foo foo = bar2FooConverter.convert(bar);
fooDao.create(foo);
}
}
you will be able to test what's really important to LeeFooService: The flow of the calls. The tests of the conversion from Foo to Bar will be the responsability of the unit tests from BarToFooConverter. An example test of LeeFooService would be
#RunWith(MockitoJUnitRunner.class)
public class LeFooServiceTest {
#Mock
private FooDao fooDao;
#Mock
private BarToFooConverter converter;
#InjectMocks
private LeeFooService service;
#Test(expected = ConversionException.class)
public void shouldForwardConversionException() {
// given
given(converter.convert(Mockito.any(Bar.class))
.willThrown(ConversionException.class);
// when
service.createAsFoo(mock(Bar.class));
// then should have thrown exception
}
#Test
public void shouldCreateConvertedFooAtDatabase() {
// given
Foo convertedFoo = mock(Foo.class);
given(converter.convert(Mockito.any(Bar.class))
.willReturn(convertedFoo);
// when
service.createAsFoo(mock(Bar.class));
// then
verify(fooDao).create(convertedFoo);
}
}
Hope that helped somehow :)
Some links that might be useful:
SOLID
BDD Mockito
As a parent would tell their child: DON'T EXPOSE YOUR PRIVATES!
You don't need to expose your private methods to test them. You can get 100 PERCENT test coverage of your class, including those private methods, without exposing them.
The rub is that some people think the 'unit' in unit testing is the function, when it's really the class.
For example: I have a class with 1 public method:
bool CheckIfPalindrome(string wordToCheck).
Internally, I have private methods to validate the length of the wordToCheck, if it's null, if it's empty, bla bla bla.
But as the tester, I don't need to know or care about how I the developer organized (or will organize) the internal code. I'm testing the implementation of the interface.
'Given the word is "Mike", When CheckIfPalindronme is called, it should return false'
'Given the word is "Mom", When CheckIfPalindronme is called, it should return true'
'Given the word is "", When CheckIfPalindronme is called, it should return false'
'Given the word is null, When CheckIfPalindronme is called, it should throw an error'
If I cover all of the possible inputs and expected outputs, I will be testing your private functions.
This is the basis of TDD / BDD, without this, TDD wouldn't be possible because we would have to wait and see how did you decide to organize your code before we can write our test.
TDD / BDD says write your tests before you even write your code (and it works great btw! It identifies flaws in requirements / design very quickly)
A class containing one public method and 14 private methods, is close to impossible to test. Without having seen it, I would be willing to bet, that it is very un-SOLID. Like JB Nizet says; me and my purist colleaagues would extract most or all private methods to helper classes. The reasons are:
Easy to test
Easy to refactor
Easy to read
Easy to reuse
The reason not to extract:
* A lot!! of classes
* It takes time to extract
* At times, performance issues hinder the pretty-ness of "proper" design.
IMHO extraction of logic should always be considered in case of:
Private methods
Big classes (I usually start to think of it when
the vertical scrollbar appears in my editor winow )
Loops within
loops
The keyword here is Single Responsibility (SRP).

Categories