How can I test this method :
public void updateTable() {
try {
String sql = "select * from userDetails";
rs = st.executeQuery(sql);
st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
table.setModel(DbUtils.resultSetToTableModel(rs));
}
catch(Exception e) {
}
Few suggestions to make this more testable.
updateTable method is doing two things here.
Execute query and get results
Apply the result set to the table.
I would refactor to have two methods.
public ResultSet getResultSetForQuery(String sql,Statement st)
public Table updateTable(ResultSet rs)
Writing tests for the above two methods should be straightforward.
There are so many java libraries available to mock the large data to help testing database related methods. For example Mockito / EasyMock / JMock and more. You can make use of these libraries. You can mock the expected results using the tools and you can test your methods with the expected results.
JUnit: In general, you write a test class like the following and annotate the method(s) that contains you test with #Test. If you want to write a test that has to fail, you can use the 'expected' attribute of the annotation. If you know your test might be running for too long and want it to timeout after a certain period of time, use the 'timeout' attribute in the annotation.
If you have certain logic for initialization before each test method, you put that into another method and annotate that one with #Before. Likewise, to free stuff up, you use #After. For initialization that is to be run once per test class, use the annotation #BeforeClass and make sure that method is public and static - same story with #AfterClass.
In general, in each test method you go like this: Execute some of your code and then make assertions about what you would expect to be the case. In my example, I am testing the method 'myAdd' and I expect that 1+1 adds up to two 2.
public class MyTest {
#Test
public void testAddition() {
int sum = myAdd(1, 1);
assertEquals(2, sum);
}
}
This example is based on JUnit: https://github.com/junit-team/junit/wiki
There are alternatives, like TestNG: http://testng.org/doc/index.html
If you want to test the behaviour of a certain class in relation to its depdencies, a mock framework is recommended. Examples include: jmock, mockito, etc
The two main points of any good test are:
Check that it works well
Localize the error if it's exist
Check that it works well
Localize the error if it's exist
In your case we cannot perform such a good testing to localize the error if it's exist because your method does too complex job. It wold be good to refactor your method into several methods to make it more readable and testable. I agree with #AjayGeorge about the way to separate that method.
And then you can write something like:
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.sql.ResultSet;
public class TestExample {
#BeforeClass
public static void setup() {
// init your connection here
// and insert data for tests
}
#AfterClass
public static void cleanup() {
// close connection
}
#Test
public void testTableUpdate() {
// initialize 'sqlQuery' and 'statement'
ResultSet resultSet = getResultSetForQuery(sqlQuery, statement);
// check 'resultSet' with JUnit methods like assertTrue
updateTable(resultSet);
// check that table is filled as you expected
}
}
Related
I have the following method and I wrote a unit test in Java for this method. It is coveraged except from the if statement and I also need to test this part.
#InjectMocks
private ProductServiceImpl productService;
public void demoMethod(final List<UUID> productUuidList) {
if (productUuidList.isEmpty()) {
return;
}
final Map<ProductRequest, PriceOverride> requestMap = getPriceRequests(uuidList);
productService.updateByPriceList(priceRequestMap, companyUuid);
}
However, as the method execution is finalized and does not return anything when uuidList is empty, I cannot test this if block.
So:
How can I test this if block?
Should I create a new Unit Test method for testing this if block? Or should I add related assert lines to the current test method?
Update: Here is my test method:
#Test
public void testDemoMethod() {
final UUID uuid = UUID.randomUUID();
final List<Price> priceList = new ArrayList<>();
final Price price = new Price();
price.setUuid(uuid);
priceList.add(price);
productService.demoMethod(Collections.singletonList(uuid));
}
The general idea is that you don't want to test specific code, but you want to test some behaviour.
So in your case you want to verify that getPriceRequests and priceService.updateByPriceList are not called when passing in an empty List.
How exactly you do that depends on what tools you have available. The easiest way is if you already mock priceService: then just instruct your mocking liberary/framework to verify that updateByPriceList is never called.
The point of doing a return in your if condition is that the rest of the code is not executed. I.e., if this // code omitted for brevity was to be executed, the method would not fill it's purpose. Therefore, just make sure that whatever that code does, it was not done if your list is empty.
You have 3 choices:
Write a unit test with mocks. Mockito allows you to verify() whether some method was invoked.
Write a more high-level test with database. When testing Service Facade Layer this is usually a wiser choice. In this case you can obtain the resulting state of DB in your test to check whether it did what it had to.
Refactor your code to work differently
Check out Test Pyramid and How anemic architecture spoils your tests for more details.
I have a doubt in TestNG with Java. I am completly new to TestNG. My doubt is, How all the test cases are executing using TestNG in java without having main() method? Please suggest me if you have any ideas. Following code is the example of a sample test case using TestNG in java. But if you notice, you can find one thing that there is no main() method in the code. Then, how does the testcases are executing?
I have another doubt. Is main() method needed for selenium Webdriver and TestNG combination to execute a script? Or can we execute testcases without main() method? If we can execute testcases without main(), then how does it is possible?
package com.first.example;
import org.testng.annotations.Test;
public class demoOne {
#Test
public void firstTestCase()
{
System.out.println("im in first test case from demoOne Class");
}
#Test
public void secondTestCase()
{
System.out.println("im in second test case from demoOne Class");
}
}
This is a valid doubt many testers have. Because the main() method is needed to run the Java program and while writing tests in TestNg we don't use main() method, and we use Annotations instead.
Annotations in TestNG are lines of code that can control how the method below them will be executed. So, in short you don't need to write main() method, TestNg do that by itself. Refer the code at the end in Annotations documentation to get the idea how it happens.
As rightly pointed out in this answer: https://stackoverflow.com/a/1918154/3619412
Annotations are meta-meta-objects which can be used to describe other
meta-objects. Meta-objects are classes, fields and methods. Asking an
object for its meta-object (e.g. anObj.getClass() ) is called
introspection. The introspection can go further and we can ask a
meta-object what are its annotations (e.g. aClass.getAnnotations).
Introspection and annotations belong to what is called reflection and
meta-programming.
Also, it's not necessary to have main() method in your tests, but you can use main() method to run the TestNg tests if you want. Refer this.
to run script from cmd prompt we use below statement,
java org.testng.TestNG testng1.xml
main method in TestNG.java class how accept the command line argument,
public static void main(String[] argv) {
TestNG testng = privateMain(argv, null);
System.exit(testng.getStatus());
}
You saw it right. Test-cases get executed through testng, the testing framework which was inspired from junit without having the main() method but extensively uses annotations.
Annotations
As per the documentation in Annotations majority of the APIs require a huge amount of boilerplate code. To write a web service you need to provide a paired interface and implementation. This boilerplate could be automatically generated by a tool if the program can be decorated with annotations indicating which methods were remotely accessible. Annotations doesn't affects the program semantics directly but they do affect the way programs are treated by tools and libraries, which can in turn affect the semantics of the running program.
TestNG
TestNG is a simple annotation-based test framework which uses a marker annotation type to indicate that a method is a test method and should be run by the testing tool. As an example:
import org.testng.annotations.Test;
#Test
public void foo() {
System.out.println("With in foo test");
}
The testing tool which is being used is as follows:
import java.lang.reflect.*;
public class RunTests {
public static void main(String[] args) throws Exception {
int passed = 0, failed = 0;
for (Method m : Class.forName(args[0]).getMethods()) {
if (m.isAnnotationPresent(Test.class)) {
try {
m.invoke(null);
passed++;
} catch (Throwable ex) {
System.out.printf("Test %s failed: %s %n", m, ex.getCause());
failed++;
}
}
}
System.out.printf("Passed: %d, Failed %d%n", passed, failed);
}
}
I'm testing different parts of a miniature search engine, and some of the JUnit tests are leaving entries in the index that interfere with other tests. Is there a convention in JUnit/Maven for clearing objects between tests?
There are 2 particular annotations that can help you with this, and are intended to be used in cases such as yours:
#After defines that a certain method must be executed after every #Test, while #AfterClass is the method to execute once the entire test class has been executed. Think of the latter as a last cleanup method to purge any structures or records you've been using and sharing between tests so far.
Here is an example:
#After
public void cleanIndex() {
index.clear(); //Assuming you have a collection
}
#AfterClass
public void finalCleanup() {
//Clean both the index and, for example, a database record.
}
Note: They have their counterparts (#Before and #BeforeClass) that to exactly the opposite by invoking the related methods before a #Test method and before starting to execute the #Tests defined on that class. This ones are the setUp used in previous versions of JUnit.
If you can't use annotations, the alternative is to use the good old tearDown method:
public void tearDown() {
index.clear(); //Assuming you have a collection.
}
This is provided by the JUnit framework and behaves like a method annotated with #After.
You should make use of the #Before annotation to guarantee that each test is running from a clean state. Please see: Test Fixtures.
Inside of your junit testing class, you can override the methods setup and teardown. setup will run before every one of your tests while teardown will run after every single junit test that you have.
ex:
public class JunitTest1 {
private Collection collection;
//Will initialize the collection for every test you run
#Before
public void setUp() {
collection = new ArrayList();
System.out.println("#Before - setUp");
}
//Will clean up the collection for every test you run
#After
public void tearDown() {
collection.clear();
System.out.println("#After - tearDown");
}
//Your tests go here
}
This is useful for clearing out data inbetween tests, but also allows you to not have to reinitialize your fields inside of every single test.
I have a class called Menu.java which is used as the interface for my program.
In this Menu.java class, I have a switch/case block which acts as my menu Options.
Basically, I want to use jUnit to test the output of each case in that switch/case block, but I'm struggling to find the best way to do it.
Is it best to have a seperate jUnit TestCase for each menu operation? and then use a single TestUnit to run all cases? Or is there a better way this can be done?
Many thanks.
In general, each class has a corresponding test class. So you would have a MenuTest.java to match your Menu.java. This allows you to find quickly the tests that are associated with a particular file, because of the naming convention.
Then, ideally, each test would have one test method associated with it. So if your switch has 10 cases, you would end up with 10 test methods, one for each case. This allows you to isolate quickly the option that is failing, because you get feedback for each test individually.
Note that TestCase is JUnit 3. If possible, use JUnit 4 tests (org.junit.*), these are annotated with a #Test annotation.
I would use a single test case for each possible work flow. Ideally you would have one assertion per test case, which is probably easier following that guideline. In general you want to keep your unit tests small and concise.
Then I would place all the test cases in the same test class as long as they belong to the same tested class.
I'd create a single class for Menu.java (MenuTest.java). I'd write a test case for each menu option. If you have GUI stuff, separate it from the logic.
No need to test the GUI or its plumbing.
If the method you are testing is receiving different parameters for this switch, consider using a parameterized test case. The advantage is that it's easier to keep track of what need to be changed if your switch changes:
Here is how it works with TestNG (look up "parameterized test case" for JUnit)
// This method will provide data to any test method that declares that
// its Data Provider is named "test1"
#DataProvider(name = "test1")
public Object[][] createData1() {
return new Object[][] {
{ "Foo", new Integer(36) },
{ "Bar", new Integer(37)},
};
}
// This test method declares that its data should be supplied by the
// Data Provider named "test1"
#Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
System.out.println(n1 + " " + n2);
}
In your case I'd use single test case for all options. You need something like this:
import org.junit.Test;
import org.junit.Assert;
import your.project.Menu;
public class MenuTest {
#Test
public void testCase() {
Menu menu = new Menu();
assertEquals("1",menu.runCase("bar"));
assertEquals("2",menu.runCase("foo"));
//etc
}
}
The selenium tests I'm gonna be doing are basically based on three main steps, with different parameters. These parameters are passed in from a text file to the test. this allows easy completion of a test such as create three of "X" without writing the code to do the create three times in one test.
Imagine i have a test involving creating two of "X" and one of "Y". CreateX and CreateY are already defined in separate tests. Is there a nice way of calling the code contained in createX and createY from say, Test1?
I tried creating a class with the creates as seperate methods, but got errors on all the selenium.-anything-, ie every damn line. it goes away if i extend seleneseTestCase, but it seems that my other test classes wont import from a class that extends seleneseTestCase. I'm probably doing something idiotic but i might as well ask!
EDIT:
well for example, its gonna be the same setUp method for every test, so id like to only write that once... instead of a few hundred times...
public void ready() throws Exception
{
selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://localhost:9443/");
selenium.start();
selenium.setSpeed("1000");
selenium.setTimeout("999999");
selenium.windowMaximize();
}
thats gonna be used EVERYWHERE.
its in a class called reuseable. Id like to just call reuseable.ready(); from the tests SetUp... but it wont let me....
public class ExampleTest {
#Before
public void setup() {
System.out.println("setup");
}
public void someSharedFunction() {
System.out.println("shared function");
}
#Test
public void test1() {
System.out.println("test1");
someSharedFunction();
}
#Test
public void test2() {
System.out.println("test2");
someSharedFunction();
}
}
The contents of the function after the #Before annotation is what will be executed before every test. someSharedFunction() is an example of a 'reusable' function. The code above will output the following:
setup
test1
shared function
setup
test2
shared function
I would recommend using JUnit and trying out some of the tutorials on junit.org. The problem you have described can be fixed using the #Before annotation on a method that performs this setup in a super class of your tests