I've written below SpringBatch job, it will read data from source table, process and write data into target table. The functionality is working as expected but I need to write Junit test cases for SpringBatch job. Can anyone help me out how to write JUnit test cases for SpringBatch job?
Here are the piece of code
#Bean(name = Constant.CREATE_JOB)
public Job testJob() {
Job job = null;
try {
Flow flowOne = new FlowBuilder<SimpleFlow>(Constant.FLOW_ONE)
.start(truncateTableStep())
.on(Constant.FAILED)
.fail()
.from(truncateTableStep())
.on(Constant.COMPLETED)
.to(firstStep())
.next(secondStep())
.build();
Flow flowTwo = new FlowBuilder<SimpleFlow>(Constant.FLOW_TWO)
.start(thridStep())
.next(fourthStep()).build();
job = jobBuilderFactory.get(Constant.CREATE_JOB)
.listener(createJobListener)
.start(flowOne)
.split(new SimpleAsyncTaskExecutor())
.add(flowTwo)
.end()
.build();
} catch (Exception exception) {
log.error("Exception while building Create job.. {}", exception.toString());
}
return job;
}
#Bean
public Step firstStep() {
Step step = null;
try {
step = stepBuilderFactory.get(Constant.POPULATE_STEP)
.<InputModel, InputModel>chunk(Constant.CHUNK_SIZE_HUNDERED)
.reader(createJobReader.createReader())
.processor(createJobCommonStepProcessor)
.writer(testWriter.testWriter())
.faultTolerant().skipLimit(10).skip(Exception.class)
.retryLimit(3)
.retry(TransientDataAccessException.class)
.listener(retryListener).build();
} catch (final Exception exception) {
log.error("Exception in the populate first Step Create Job: {}",
exception.toString());
}
return step;
}
#Bean
public Step secondStep() {
........
}
#Bean
public Step thirdStep() {
........
}
#Bean
public Step fourthStep() {
........
}
Related
I am writing integration tests using Junit 5.
I should run each test with privileged action (as logged in user).
I could achieve it by calling using Subject.doAs from each test like this:
Subject.doAs(systemSubject, (PrivilegedAction<Object>) () -> actualMethodToBeTested();
But is there any way to achieve this by using Extension in Junit 5? The reason is to avoid calling the Subject.doAs in each method.
In Junit 4, I could achieve it with the use of test decorators and runners.
Simplified version of my Junit 4 runner:
#Override
public void run(RunNotifier notifier) {
try {
Object testObject = testClass.newInstance();
for (Method method : testClass.getMethods()) {
if (method.isAnnotationPresent(Test.class)) {
notifier.fireTestStarted(Description
.createTestDescription(testClass, method.getName()));
final Subject systemSubject = getSystemSubject();
Subject.doAs(systemSubject, (PrivilegedAction<Object>)
() -> {
try {
return method.invoke(testObject);
} catch (IllegalAccessException e) {
return null;
} catch (InvocationTargetException e) {
return null;
}
});
notifier.fireTestFinished(Description
.createTestDescription(testClass, method.getName()));
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public class FileUtil {
public void methodOne(Bean bean) {
StringBuffer profileControlValue = new StringBuffer();
profileControlValue.append(bean.getName()).append(bean.getDesc());
String sourcePath = "path to save";
try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(sourcePath.toString())))) {
writer.write(profileControlValue.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
I want to write a Junit test case using Mockito/PowerMockito for above method.
Basically I have a method which accepts Bean and process the values and writes it into file.
For Eg:
Below is my test method and data provider. my testmethod should be skipped if data provider input is "Two".
#Test(dataprovider = "getData")
public void test(String data) {
System.out.println(data + " Executed successfully");
}
#DataProvider
public Object[][] getData(){
return new Object[][]{
{"One"},
{"Two"},
{"Three"},
{"Four"},
{"Five"}
};
}
inside your test method , you can compare the parameter data and throw a skip exception when your condition is satisfied.
#Test(dataprovider = "getData")
public void test(String data) {
if(data.equals("two")){
throw new SkipException("Test skipped as data is:"+data);
}
System.out.println(data + " Executed successfully");
}
We have a text file where a list of search query and the expected result is given. Such as,
Search Result
a:120 result1
b:220 result2
.....
.....
Now, we need to write a JUnit (heavily used in our daily build) test class, where each of the row will represent one #Test method. So by that, we know, which search case failed (UI).
We already have a solution, where we have one #Test method only, and we have log to check which case passed or failed.
But, we are trying to achieve per case represented as a junit method. Is it really possible, to dynamically create a #Test method to JUnit architecture.
Our, #Test method is same for every search case. That means, we just want to pass a different parameter every time.
I have come up with a JUnit3 solution to my problem. Need help to translate it to Junit4.
public static Test suite()
{
TestSuite suite = new TestSuite();
for ( int i = 1; i <= 5; i++ ) {
final int j = i;
suite.addTest(
new Test1( "testQuery" + i ) {
protected void runTest()
{
try {
testQuery( j );
} catch ( MalformedURLException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch ( SolrServerException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
);
}
return suite;
}
In JUnit 4 there is a concept called "Parameterized Test" that is used for exactly this.
I don't fully understand your test above, but this should give you a hint:
#RunWith(Parameterized.class)
public class ParameterizedTest {
private String query;
private String expectedResult;
public ParameterizedTest(String query, String expectedResult) {
this.query = datum;
this.expectedResult = expectedResult;
}
#Parameters
public static Collection<Object[]> generateData() {
Object[][] data = {
{ "a:120", "result1" },
{ "b:220", "result2" },
};
return Arrays.asList(data);
}
#Test
public void checkQueryResult() {
System.out.println("Checking that the resutl for query " + query + " is " + expectedResult);
// ...
}
}
I'm pretty new to programming with java but I've tried to directly start with unit-testing and therefore also used JMock. I have already implemented some test-cases (with JMock) that work, but this one I just can't get to run.
What I did:
I wrote a test-class which creates a mock object and then I'm expectation one (using oneOf) invocation. After running the unit test it says it fails (but the logs say otherwise, as i print out the data I returned at the invocation using will(returnValue(x)).
The next funny/weird thing is - if I change the oneOf to "never" the unit test succeeds, but it throws an Exception:
Exception in thread "Thread-2" java.lang.AssertionError: unexpected invocation: blockingQueue.take()
expectations:
expected never, never invoked: blockingQueue.take(); returns
what happened before this: nothing!
Here the code:
#RunWith(JMock.class)
public class ExecuteGameRunnableTest {
private Mockery context = new JUnit4Mockery();
private Thread testObject;
private BlockingQueue<Game> queueMock;
private Executor executorMock;
#SuppressWarnings("unchecked")
#Before
public void setUp() {
queueMock = context.mock(BlockingQueue.class);
executorMock = context.mock(Executor.class);
testObject = new Thread(new ExecuteGameRunnable(queueMock, executorMock, true));
}
#After
public void tearDown() {
queueMock = null;
executorMock = null;
testObject = null;
}
#Test
public void testQueueTake() throws InterruptedException {
final Game game = new Game();
game.setId(1);
game.setProcessing(false);
context.checking(new Expectations() {{
never(queueMock).take(); will(returnValue(game));
}});
testObject.start();
context.assertIsSatisfied();
}
}
and the runnable that I'm testing:
public class ExecuteGameRunnable implements Runnable {
private BlockingQueue<Game> queue;
private Executor executor;
private Boolean unitTesting = false;
static Logger logger = Logger.getLogger(ExecuteGameRunnable.class);
public ExecuteGameRunnable(BlockingQueue<Game> queue, Executor executor) {
this.queue = queue;
this.executor = executor;
}
public ExecuteGameRunnable (BlockingQueue<Game> queue, Executor executor, Boolean unitTesting) {
this(queue,executor);
this.unitTesting = unitTesting;
}
public void run() {
try {
do {
if (Thread.interrupted()) throw new InterruptedException();
Game game = queue.take();
logger.info("Game "+game.getId()+" taken. Checking if it is processing"); // THIS ONE PRINTS OUT THE GAME ID THAT I RETURN WITH JMOCK-FRAMEWORK
if (game.isProcessing()) {
continue;
}
game.updateProcessing(true);
executor.execute(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
} while (!unitTesting);
} catch (InterruptedException ex) {
logger.info("Game-Execution-Executor interrupted.");
return;
} catch (DataSourceException ex) {
logger.fatal("Unable to connect to DB whilst executing game: "+id_game,ex);
return;
}
}
}
JMock isn't thread safe. It's intended to support unit testing, rather than what is a very small integration test. Frankly, in this case I'd use a real BlockingQueue rather than a mock one. And there is no way you should have a unitTesting flag in your production code.
One more thing, you don't need to set the fields in the test class to null, jUnit flushes the instance for every test.