issue with junit test case! avoid code duplication - java

I am writting jnuit test case for testing API.
my class is as follows
class MyTest extends TestCase{
List<String> argList;
public MyTest(){
//read argList from File
}
testMyTest(){
//callmy api
myApi(arg1);
}
}
Now i want make a seperate testcase for each of the 50 args.Args are read from File. I dont want to write a seperate method for calling myApi with different args.How can i do it?
I dont want to write sperate methods like
testMyTest1(){
//callmy api
myApi(arg1);
}
testMyTest1(){
//callmy api
myApi(arg2);
}

You can use a parameterized test for this.

You can use a Parameterized tests or Theories (since JUnit 4.4). For more details use
http://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit
http://blogs.oracle.com/jacobc/entry/junit_theories

private static final String[] args = new String[] {.....};
#Test
public void myTest(){
for (int i=0; i<args.length; i++){
myApi(args[i];
}
}
The above answers your question I think, however it is not good JUnit practice. It is best that each test method only invokes the method under test one time with one test condition. That way if multiple things are wrong, you get a separate error for each rather than dealing with one at a time. This would suggest the following:
private static final String[] args = new String[] {.....};
private void testMyTest(String arg){
myApi(arg);
}
#Test
public void myTest0(){
testMyTest(args[0]);
}
#Test
public void myTest1(){
testMyTest(args[1]);
}
Probably the best mechanism is to do the first option above but using the ErrorCollector rule to allow for multiple errors to be reported.
Edit I stand corrected, jordao's answer regarding parameterized tests is really the best way to do this.

Unit testing usually is made with assertions. You don't need to write a method for each argument, but execute different assertions based on your arguments.
One way for doing it would be:
class MyApiTest extends TestCase {
List<String> argList;
public MyApiTest() {}
public testMyApi() {
assertTrue(testMyApi(arg1));
assertFalse(testMyApi(arg2));
assertNull(testMyApi(arg3));
assertEquals(testMyApi(arg4), testMyApi(arg5));
}
}
I'd even prefer using annotations, like
class MyApiTest {
#Before
public setUp() {}
#After
public tearDOwn() {}
#Test
public testMyApi() {
Assert.assertTrue(testMyApi(arg1));
Assert.assertFalse(testMyApi(arg2));
Assert.assertNull(testMyApi(arg3));
Assert.assertEquals(testMyApi(arg4), testMyApi(arg5));
}
}

Related

blend parameterized and programmatic unit tests

With JUnit you can use #RunWith(Parameterized.class) to provide a set of parameters to pass to the test constructor and then run tests with each object.
I'm trying to move as much test logic as possible into data, but there are some tests that won't easily be converted into data-driven tests. Is there a way to use JUnit's Parameterized runner to run some tests with parameters, and then also add non-data-driven tests that aren't run repeatedly for each test object construction?
My workaround for this was to create a single class and place the programmatic and data-driven tests in two separate sub-classes. A sub-class must be static for JUnit to run its tests. Here's a skeleton:
#RunWith(Enclosed.class) // needed for working well with Ant
public class MyClassTests {
public static class Programmatic {
#Test
public void myTest(){
// test something here
}
}
#RunWith(Parameterized.class)
public static class DataDriven {
#Parameters
public static Collection<Object[]> getParams() {
return Collections.emptyList();
}
private String data;
public DataDriven(String testName, String data){
this.data = data;
}
#Test
public void test() throws AnalyzeExceptionEN{
// test data string here
}
}
}
one way is to use Junit's Enclosed runner. it's very verbose but also pretty powerful. it allows you to combine multiple different runners in one file.
other option is to use custom junit runner. for sure zohhak supports tests with parameters and without. small extract:
#RunWith(ZohhakRunner.class)
public class CoercingTest {
#TestWith("ONE_OF_ENUM_VALUES")
public void should_coerce_enum(SampleEnum param) {
assertThat(param).isEqualTo(SampleEnum.ONE_OF_ENUM_VALUES);
}
#Test
public void should_run_standard_junit_test() {
//this will also work
}
}
if it's not enough for you, for sure you can find other runners that support both kind of tests.

JUNIT : run setup only once for a large number of test classes

I have a class, which I use as a basis for my unit tests. In this class I initialize the whole environment for my tests, setting up database mappings, enter a number of database records across multiple tables, etc. That class has a method with a #BeforeClass annotation which does the initialization. Next thing, I extend that class with specific classes in which I have #Test methods.
My question is, since the before class is exactly the same for all these test classes, how can I ensure that they are run only once for all the tests.
One simple solution is that I could keep all the tests in one class. However, the number of tests is huge, also they are categorised based on functional heads. So they are located in different classes. However since they need the exact same setup, they inherit the #BeforeClass. As a result the whole setup is done at least once per test class, taking much more time in total than I would prefer.
I could, though, put them all in various subpackages under one package, hence if there is a way, how I can run set up once for all the tests within that package, it would be great.
With JUnit4 test suite you can do something like this :
#RunWith(Suite.class)
#Suite.SuiteClasses({ Test1IT.class, Test2IT.class })
public class IntegrationTestSuite
{
#BeforeClass
public static void setUp()
{
System.out.println("Runs before all tests in the annotation above.");
}
#AfterClass
public static void tearDown()
{
System.out.println("Runs after all tests in the annotation above.");
}
}
Then you run this class as you would run a normal test class and it will run all of your tests.
JUnit doesn't support this, you will have to use the standard Java work-arounds for singletons: Move the common setup code into a static code block and then call an empty method in this class:
static {
...init code here...
}
public static void init() {} // Empty method to trigger the execution of the block above
Make sure that all tests call init(), for example my putting it into a #BeforeClass method. Or put the static code block into a shared base class.
Alternatively, use a global variable:
private static boolean initialize = true;
public static void init() {
if(!initialize) return;
initialize = false;
...init code here...
}
Create one base class for all tests:
public class BaseTest {
static{
/*** init code here ***/
}
}
and every test should inherit from it:
public class SomeTest extends BaseTest {
}
You can make one BaseTest class with a #BeforeClass method, then have all the other tests inherit from it. This way, when each test object is constructed, #BeforeClass gets executed.
Also avoid executing it just once for all the test suite, since all the test cases should be independent. #BeforeClass should execute only once each test case, not test suite.
If you can tolerate adding spring-test to your project, or you are using it already, then a good approach is to use the technique described here: How to load DBUnit test data once per case with Spring Test
Not sure if anyone still is using JUnit and trying to fix it without using Spring Runner (aka no spring integration). TestNG has this feature. But here is a JUnit based solution.
Create a RunOnce per thread operation like so. This maintains a list of classes for which the operation has run.
public class RunOnceOperation {
private static final ThreadLocal t = new ThreadLocal();
public void run(Function f) {
if (t.get() == null) {
t.set(Arrays.asList(getClass()));
f.apply(0);
} else {
if (!((List) t.get()).contains(getClass())) {
((List) t.get()).add(getClass());
f.apply(0);
}
}
}
}
Back in your unit test
#Before
public beforeTest() {
operation.run(new Function<Integer, Void>() {
#Override
public Void apply(Integer t) {
checkBeanProperties();
return null;
}
});
}
private void checkBeanProperties() {
//I only want to check this once per class.
//Also my bean check needs instance of the class and can't be static.
}
My function interface is like this:
interface Function<I,O> {
O apply(I i);
}
When you use this way, you can perform operations once per class using ThreadLocal.

How to verify static void method has been called with power mockito

I am using the following.
Powermock-mockito 1.5.12
Mockito 1.95
junit 4.11
Here is my utils class
public void InternalUtils {
public static void sendEmail(String from, String[] to, String msg, String body) {
}
}
here is gist of the class under test:
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail(...);
}
}
}
And here is the test:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalService {
public void verifyEmailSend() {
mockStatic(Internalutils.class);
doNothing().when(InternalUtils, "sendEmail", anyString(), any(String.class), anyString(), anyString());
Order order = mock(Order.class);
when(order.isSuccessful()).thenReturn(true);
InternalService is = new InternalService();
verifyStatic(times(1));
is.processOrder(order);
}
}
The above test fails. The verification mode given is none, but according to the code, if order is successful than email must be send.
If you are mocking the behavior (with something like doNothing()) there should really be no need to call to verify*(). That said, here's my stab at re-writing your test method:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest { //Note the renaming of the test class.
public void testProcessOrder() {
//Variables
InternalService is = new InternalService();
Order order = mock(Order.class);
//Mock Behavior
when(order.isSuccessful()).thenReturn(true);
mockStatic(Internalutils.class);
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
//Execute
is.processOrder(order);
//Verify
verifyStatic(InternalUtils.class); //Similar to how you mock static methods
//this is how you verify them.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
}
}
I grouped into four sections to better highlight what is going on:
1. Variables
I choose to declare any instance variables / method arguments / mock collaborators here. If it is something used in multiple tests, consider making it an instance variable of the test class.
2. Mock Behavior
This is where you define the behavior of all of your mocks. You're setting up return values and expectations here, prior to executing the code under test. Generally speaking, if you set the mock behavior here you wouldn't need to verify the behavior later.
3. Execute
Nothing fancy here; this just kicks off the code being tested. I like to give it its own section to call attention to it.
4. Verify
This is when you call any method starting with verify or assert. After the test is over, you check that the things you wanted to have happen actually did happen. That is the biggest mistake I see with your test method; you attempted to verify the method call before it was ever given a chance to run. Second to that is you never specified which static method you wanted to verify.
Additional Notes
This is mostly personal preference on my part. There is a certain order you need to do things in but within each grouping there is a little wiggle room. This helps me quickly separate out what is happening where.
I also highly recommend going through the examples at the following sites as they are very robust and can help with the majority of the cases you'll need:
https://github.com/powermock/powermock/wiki/Mockito (PowerMock Overview / Examples)
http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html (Mockito Overview / Examples)
Thou the above answer is widely accepted and well documented, I found some of the reason to post my answer here :-
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
Here, I dont understand why we are calling InternalUtils.sendEmail ourself.
I will explain in my code why we don't need to do that.
mockStatic(Internalutils.class);
So, we have mocked the class which is fine.
Now, lets have a look how we need to verify the sendEmail(/..../) method.
#PrepareForTest({InternalService.InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest {
#Mock
private InternalService.Order order;
private InternalService internalService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
internalService = new InternalService();
}
#Test
public void processOrder() throws Exception {
Mockito.when(order.isSuccessful()).thenReturn(true);
PowerMockito.mockStatic(InternalService.InternalUtils.class);
internalService.processOrder(order);
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
}
}
These two lines is where the magic is,
First line tells the PowerMockito framework that it needs to verify the class it statically mocked. But which method it need to verify ??
Second line tells which method it needs to verify.
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
This is code of my class, sendEmail api twice.
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail("", new String[1], "", "");
InternalUtils.sendEmail("", new String[1], "", "");
}
}
public static class InternalUtils{
public static void sendEmail(String from, String[] to, String msg, String body){
}
}
public class Order{
public boolean isSuccessful(){
return true;
}
}
}
As it is calling twice you just need to change the verify(times(2))... that's all.

Conditionally ignoring tests in JUnit 4

OK, so the #Ignore annotation is good for marking that a test case shouldn't be run.
However, sometimes I want to ignore a test based on runtime information. An example might be if I have a concurrency test that needs to be run on a machine with a certain number of cores. If this test were run on a uniprocessor machine, I don't think it would be correct to just pass the test (since it hasn't been run), and it certainly wouldn't be right to fail the test and break the build.
So I want to be able to ignore tests at runtime, as this seems like the right outcome (since the test framework will allow the build to pass but record that the tests weren't run). I'm fairly sure that the annotation won't give me this flexibility, and suspect that I'll need to manually create the test suite for the class in question. However, the documentation doesn't mention anything about this and looking through the API it's also not clear how this would be done programmatically (i.e. how do I programatically create an instance of Test or similar that is equivalent to that created by the #Ignore annotation?).
If anyone has done something similar in the past, or has a bright idea of how else I could go about this, I'd be happy to hear about it.
The JUnit way is to do this at run-time is org.junit.Assume.
#Before
public void beforeMethod() {
org.junit.Assume.assumeTrue(someCondition());
// rest of setup.
}
You can do it in a #Before method or in the test itself, but not in an #After method. If you do it in the test itself, your #Before method will get run. You can also do it within #BeforeClass to prevent class initialization.
An assumption failure causes the test to be ignored.
Edit: To compare with the #RunIf annotation from junit-ext, their sample code would look like this:
#Test
public void calculateTotalSalary() {
assumeThat(Database.connect(), is(notNull()));
//test code below.
}
Not to mention that it is much easier to capture and use the connection from the Database.connect() method this way.
You should checkout Junit-ext project. They have RunIf annotation that performs conditional tests, like:
#Test
#RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
//your code there
}
class DatabaseIsConnected implements Checker {
public boolean satisify() {
return Database.connect() != null;
}
}
[Code sample taken from their tutorial]
In JUnit 4, another option for you may be to create an annotation to denote that the test needs to meet your custom criteria, then extend the default runner with your own and using reflection, base your decision on the custom criteria. It may look something like this:
public class CustomRunner extends BlockJUnit4ClassRunner {
public CTRunner(Class<?> klass) throws initializationError {
super(klass);
}
#Override
protected boolean isIgnored(FrameworkMethod child) {
if(shouldIgnore()) {
return true;
}
return super.isIgnored(child);
}
private boolean shouldIgnore(class) {
/* some custom criteria */
}
}
Additionally to the answer of #tkruse and #Yishai:
I do this way to conditionally skip test methods especially for Parameterized tests, if a test method should only run for some test data records.
public class MyTest {
// get current test method
#Rule public TestName testName = new TestName();
#Before
public void setUp() {
org.junit.Assume.assumeTrue(new Function<String, Boolean>() {
#Override
public Boolean apply(String testMethod) {
if (testMethod.startsWith("testMyMethod")) {
return <some condition>;
}
return true;
}
}.apply(testName.getMethodName()));
... continue setup ...
}
}
A quick note: Assume.assumeTrue(condition) ignores rest of the steps but passes the test.
To fail the test, use org.junit.Assert.fail() inside the conditional statement. Works same like Assume.assumeTrue() but fails the test.

jUnit - How to assert that inherited methods are invoked?

Let's say you have some 3rd-party library class that you want to extend, simply to add convenience methods to it (so you can call an inherited method with default parameters for example).
Using jUnit/jMock, is it possible to write an assertion / mock expection that tests that the correct inherited method is called?
For example, something like this:
class SomeClass extends SomeLibraryClass {
public String method(String code) {
return method(code, null, Locale.default());
}
}
How can I assert that method is being called?
You can make a further subclass inside your unit test that actually tells you:
public class MyTest {
boolean methodCalled = false;
#Test
public void testMySubclass(){
TestSomeClass testSomeClass = new TestSomeClass();
// Invoke method on testSomeclass ...
assertTrue( methodCalled);
}
class TestSomeClass extends SomeClass{
public String method(String code){
methodCalled = true;
}
}
}
Unit testing is more useful to verify the functionality of given methods, not to assert coverage. Unit tests that care more about what method got called know way more about the classes they are testing than they probably should, not to mention will be confusing to the reader.
Coverage tools like Cobertura or EMMA will tell you whether you properly covered your code.
It may indeed be better to only write integration tests in this case, but if you really want a unit test, you can have it just as easily as in any other case:
public class SomeClassTest
{
#Test
public void testMethod()
{
final String code = "test";
new Expectations()
{
SomeLibraryClass mock;
{
mock.method(code, null, (Locale) any);
}
};
new SomeClass().method(code);
}
}
This test uses the JMockit mocking API.
it's hard to tell without a more concrete example, but I'd guess that this ought to be an integration test--test the whole package together--rather than a unit test. Sometimes one can be too fine-grained with unit testing.

Categories

Resources