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);
Related
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.
I am writing a test for a class which has a setup
class A
{
private String name;
public String getName()
{
return "Hello "+ name;
}
public void setName(String name)
{
this.name = name;
}
My test class
TestA
A a = new A();
{
#Before
void setup()
{
a.setName("Jack");
}
#Test
public void testTom()
{
assert(a.getString(), "Hello Tom");
}
#Test
public void testJack()
{
assert(a.getString(), "Hello Jack");
}
How to change the value of name between the methods since #Before calls for every test method?
ie) if execute testJack then the output should be Hello Jack.
I tried with #Parameters but before that setup is getting called so i couln't acheive this functionality.
First, the code:
#Before
void setup()
{
A a = new A();
a.setName("Jack");
}
Doesn't do anything which the Tests can see. You're creating a local variable a which goes out of scope almost immediately.
#Before is designed to set and reset a state or context before each Test is run. It doesn't vary unless something it relies on changes between invocations.
You could create a Stack as an instance variable and pre-populate it in a #BeforeClass method, and have #Before pop a value to be used every time it's called. This is unadvisable as it assumes that the Tests will be run in some particular order. It's much cleaner and clearer to just declare different values inside each Test.
There is simply no point in doing that; as your real problem is rooted in your statement "Just assume the scenario of 30 lines of code in setup".
If you need 30 lines of setup code, then your code under test is not following the "single responsibility principle" and doing way too many different things.
Of course, you can turn to "data driven" testing to somehow get there (see here for example); but that would be fixing the Y side of an XY problem.
I know, it sounds harsh: but you better step back; and learn about doing reasonable OO design (for example based on SOLID). Then you rework your code to not need 30 lines of setup code.
You see, if your code is so hard to test; I guarantee you: it is also hard to understand, and will be close to impossible to maintain/enhance over time. And beyond that: it will be even hard to get your code to be "correct" in the first place.
Long story short: have a look in these videos and improve your design skills.
I'm just getting started with Java, and I'm confused about how to unit test Java classes while still keeping everything isolated. Specifically, I'm wondering how I might test a method like createProgram in this example:
package com.example.app;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import com.example.data_models.Program;
public class ProgramCreator {
private PersistenceManagerFactory pm_factory;
public ProgramCreator(PersistenceManagerFactory pm_factory) {
this.pm_factory = pm_factory;
}
public void createProgram(String name, String instructor, double price) {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(new Program(name, instructor, price));
} finally {
pm.close();
}
}
private PersistenceManager getPersistenceManager()
{
return this.pm_factory.getPersistenceManager();
}
}
I'm pretty sure I can mock out the persistence manager factory using a library like mockito and use that to test that the makePersistent method is getting called with the right arguments, but how do I check that the fields of the program data model are correct while still keeping everything isolated? I don't want to rely on the program object's getter methods, as that would result in my unit tests for ProgramCreator being reliant on the Program class being correct. What do I do in this situation? (With Ruby, I'd probably just stub out the new method of the Program class. Is something like that possible in Java?)
By creating an object (Program) in createProgram method you are creating tight coupling between the objects. Instead delegate the work of creation to a factory and you can mock the factory in your unit test. This would mean we would be testing only what createProgram method is doing and nothing else. Trying to unit test code could give us indications to re-design/re-factor the code.
public class ProgramCreator {
private PersistenceManagerFactory pm_factory;
private ProgramFactory p_factory;
public ProgramCreator(PersistenceManagerFactory pm_factory, ProgramFactory pFactory) {
this.pm_factory = pm_factory;
this.p_factory = pFactory;
}
public void createProgram(String name, String instructor, double price) {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(p_Factory.createProgram(name, instructor, price));
} finally {
pm.close();
}
}
}
A unit in is not necessarily limited to a single class, it is the smallest set of classes that work together. So there is nothing wrong with using the getters from Program while testing ProgramCreator.
You don't have to test everything, everywhere.
Do as you say: mock the appropriate code to test createProgram and see if the results of that are as you expect them to be (aka: there has been a program persisted with the given fields).
You don't have to necessarily test that you actually create a new Program that has those fields. You could just as well test in a different method whether or not new Program(name, instructor, price) creates a new object with the right values.
The most important part about unit tests is this flow:
-> General idea
-> Logic performed
-> End situation reached
Your situation fills this in as
-> I want to test createProgram with variables X, Y and Z
-> ??
-> The database should return a program that has values X, Y and Z
All together you don't really care what happens in the second step, as long as the end result works. For this reason you can allow more general tests in your code that basically perform logic and check if the result of all that equals your desired output.
The obvious issue with this is ofcourse: in the case of an error, won't this mean I have to manually debug to find the issue? Yes, it does. That's why you should add many smaller tests (like testing the constructor) to help pinpoint the exact issue.
There certainly is nothing wrong with using getters and setters. In fact, you will most certainly need them. It's about testing workflow, not necessarily testing isolated methods.
I'd like to have a reflection-like solution for displaying the methods which are called.
Example:
public class Foo {
public void bar() {
new Y().x();
}
}
public class Y {
public void x() {
}
}
public class Main {
public static void main(String[] args) {
// SETTING UP THE MAGIC
new Foo().bar();
new Y().x();
}
}
The output should be:
1. Foo.bar
1.2 Y.x
2. Y.x
Optimally there could be an event handler which would be fired every time a method is called(and some info could be passed as a parameter).
PS: I don't want to use this in a production environment, I only need this for displaying output in a skeleton app without dummy copy-paste.
I would use aspectj to define an aspect which writes log messages for every method call. You can find an example here: Tracing Java Method Execution with AspectJ. or here: Logging with AspectJ
The advantage of this solution is that you don't have to make any changes on your code. You will need some time to get into aspectj, but it meets your requirement very well.
You would have to build a profiler agent if you wanted to achieve this without having to pollute your code.
Take a look at this article, it shows you how to do it. Specifically, look at profiling aspects lower in that article.
Listing 2 is a profiling aspect that can be used to output the class name, method name, and a timestamp every time the JVM enters or leaves a method.
As in the title, I want to test a method like this:
public void startThread()
{
new Thread()
{
public void run()
{
myLongProcess();
}
}.start();
}
EDIT:
Judging by comments I guess it is not very common to test if a thread starts or not. So I've to adjust the question... if my requirement is 100% code coverage do I need to test if that thread starts or not? If so do I really need an external framework?
This can be done elegantly with Mockito. Assuming the class is named ThreadLauncher you can ensure the startThread() method resulted in a call of myLongProcess() with:
public void testStart() throws Exception {
// creates a decorator spying on the method calls of the real instance
ThreadLauncher launcher = Mockito.spy(new ThreadLauncher());
launcher.startThread();
Thread.sleep(500);
// verifies the myLongProcess() method was called
Mockito.verify(launcher).myLongProcess();
}
If you need 100% coverage, you will need to call startThread which will kick off a thread. I recommend doing some sort of verification that the thread was stared (by verifying that something in myLongProcess is happening, then clean up the thread. Then you would probably do the remainder of the testing for myLongProcess by invoking that method directly from your unit test.