I have a constructor that may throw an IOException:
public MyClass(string url) throws IOException { ... }
Now I want to test of the exception is thrown in certain scenarios using a parameterized test. Can I annotate my test-method with a value for url and the expected exception, something like this?
#Test("https://myHost/not.existsing", expected = IOException.class)
#Test("https://myHost/whrong.fileextension", expected = IOException.class)
public void MyTest(String url)
{
Assert.Throws(expected);
}
Junit 4 supports Prameterized. Try this:
#RunWith(Parameterized.class)
public class Test {
#Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ "https://myHost/whrong.fileextension" },
{ "https://myHost/not.existsing"}
});
}
private String url;
public Test(String url) {
this.url = url;
}
#Test(expected = IOException.class)
public void test() throws IOException {
MyClass myClass = new MyClass(url);
}
}
Related
Jmockit is very powerful, but sometimes I cannot understand what it does behind the scene, so I have a question regarding jmockit. Hopefully the more experienced programmers on here could help shine some light on this situation :)
I have the following two classes in two separate files:
public class SmallClass {
String a;
SmallClass(String arg) throws Exception {
a = arg;
}
public String getString() {
return a;
}
}
And
public class BigClass {
private static final SmallClass smallClass;
static {
try {
smallClass = new SmallClass("dummy");
} catch (Exception e) {
throw new IllegalStateException("Could not initialized", e);
}
}
public static String getString() {
return smallClass.getString();
}
}
Now, I have a class to test BigClass:
public class BigClassTest {
#Test
public void testGet() throws Exception {
///CLOVER:OFF
new MockUp<SmallClass>() {
#Mock
public void $init(String string) throws Exception {
//Do nothing
}
#Mock
public String getString() {
return "dummyString";
}
};
///CLOVER:ON
Assert.assertEquals("dummyString", BigClass.getString());
}
#Test(expected = ExceptionInInitializerError.class)
public void testException() throws Exception {
///CLOVER:OFF
new MockUp<SmallClass>() {
#Mock
public void $init(String string) throws Exception{
throw new Exception("Mocked Exception");
}
};
///CLOVER:ON
BigClass.getString();
}
}
If I run each of these independently, then they each passes. But if I run the whole test file, then the first test fails with:
java.lang.NoClassDefFoundError: Could not initialize class BigClass
I also tried tearing down the mock after each test like this, but it doesn't help:
public class BigClassTest {
MockUp<SmallClass> smallClassMockUp;
#Test
public void testGet() throws Exception {
///CLOVER:OFF
smallClassMockUp = new MockUp<SmallClass>() {
#Mock
public void $init(String string) throws Exception {
//Do nothing
}
#Mock
public String getString() {
return "dummyString";
}
};
///CLOVER:ON
Assert.assertEquals("dummyString", BigClass.getString());
smallClassMockUp.tearDown();
}
#Test(expected = ExceptionInInitializerError.class)
public void testException() throws Exception {
///CLOVER:OFF
smallClassMockUp = new MockUp<SmallClass>() {
#Mock
public void $init(String string) throws Exception{
throw new Exception("Mocked Exception");
}
};
///CLOVER:ON
BigClass.getString();
smallClassMockUp.tearDown();
}
}
Any help would be appreciated. Thank you in advance!
The occurrence of NoClassDefFoundError, in a case like this, is not because the class wasn't found by the JVM (it was), but because its static initialization has failed (by throwing an exception or error from the execution of a static initializer). Once this happens, the class is left in an invalid/uninitialized state and cannot be used in the same JVM instance anymore.
For reference, see the "Initialization of classes and interfaces" section in the JLS.
Also, note that the order in which tests execute is not necessarily the textual order they appear in the test class. Here, testException (the second test) runs first. So, when testGet runs, the class is invalid and the JVM throws the error.
I have about 15 JUnit test cases each one which needs a difference resource file from which it reads necessary input data. Currently, I'm hard coding the specific resource file path in each test case method.
#Test
public void testCase1() {
URL url = this.getClass().getResource("/resource1.txt");
// more code here
}
#Test
public void testCase2() {
URL url = this.getClass().getResource("/resource2.txt");
// more code here
}
May be I could have all these files loaded in the setUp() method into separate URL variables and then use the specific URL variable in each test method. Is there a way better way of doing this?
You can use the TestName rule.
#Rule public TestName testName = new TestName();
public URL url;
#Before
public void setup() {
String resourceName = testName.getMethodName().substring(4).toLowerCase();
url = getClass().getResource("/" + resourceName + ".txt");
}
#Test
public void testResource1() {
// snip
}
#Test
public void testResource2() {
// snip
}
Try JUnit RunWith(Parameterized.class).
Example, that takes a resource name and an int expected result :
#RunWith(Parameterized.class)
public class MyTest {
#Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{"resource1.txt", 0000}, {"resource2.txt", 9999}
});
}
public final URL url;
public final int expected;
public MyTest(String resource, int expected) {
this.url=URL url = this.getClass().getResource("/"+resource)
this.expected = expected;
}
#Before
public void setUp() {
}
#Test
public void testReadResource() throws Exception {
// more code here, based on URL and expected
}
}
More info here:http://junit.org/apidocs/org/junit/runners/Parameterized.html
I am trying to use Google ThreadWeaver to write a unit test for concurrent code. No matter what I do, I will get an IllegalArgumentException. I am still working with an example, but even that does not work. This is what I tried:
public class ExampleTest {
public static class ExampleMain implements MainRunnable<Example> {
private Example example;
#Override
public Class<Example> getClassUnderTest() {
return Example.class;
}
#Override
public String getMethodName() {
return null;
}
#Override
public Method getMethod() throws NoSuchMethodException {
return null;
}
#Override
public void initialize() throws Exception {
example = new Example();
}
#Override
public Example getMainObject() {
return example;
}
#Override
public void terminate() throws Exception {
}
#Override
public void run() throws Exception {
example.test("second");
}
}
public static class ExampleSecondary implements SecondaryRunnable<Example, ExampleMain> {
private ExampleMain exampleMain;
#Override
public void initialize(ExampleMain main) throws Exception {
exampleMain = main;
}
#Override
public void terminate() throws Exception {
}
#Override
public boolean canBlock() {
return false;
}
#Override
public void run() throws Exception {
exampleMain.getMainObject().test("main");
}
}
public static class Example {
private List<String> list = new ArrayList<String>();
public String test(String s) {
System.out.println("1" + s);
list.add(s);
System.out.println("2" + s);
return list.get(0);
}
}
#Test
public void testThreadWeaver() throws Exception {
ClassInstrumentation instrumentation = Instrumentation.getClassInstrumentation(Example.class);
Method tested = Example.class.getDeclaredMethod("test", String.class);
Method breakpoint = List.class.getDeclaredMethod("add", Object.class);
CodePosition codePosition = instrumentation.afterCall(tested, breakpoint);
InterleavedRunner.interleave(new ExampleMain(), new ExampleSecondary(), Arrays.asList(codePosition)).throwExceptionsIfAny();
}
}
The stack trace says:
java.lang.IllegalArgumentException: Class Example is not instrumented
at
com.google.testing.threadtester.CallLoggerFactory.getClassInstrumentation(CallLoggerFactory.java:108)
at
com.google.testing.threadtester.Instrumentation.getClassInstrumentation(Instrumentation.java:65)
at MyTest.testThreadWeaver(MyTest.java:92
I followed the instructions at the official Google code webpage, but it does not seem to work. Any ideas?
ThreadWeaver needs to instrument your classes in order to add breakpoints to your methods. Therefore, you cannot run the tests with JUnit directly but you must run your test from a specific test runner. For your case this would be ThreadedTestRunner. The actual test methods must then be annotated with #ThreadedTest instead of #Test. This should work:
#Test
public void startTest() throws Exception {
new ThreadedTestRunner().runTests(getClass(), Example.class);
}
#ThreadedTest
public void testThreadWeaver() throws Exception {
// here comes your test
}
I found #Rule annotation in jUnit for better handling of exception.
Is there a way to check error code ?
Currently my code looks like (without #Rule):
#Test
public void checkNullObject() {
MyClass myClass= null;
try {
MyCustomClass.get(null); // it throws custom exception when null is passed
} catch (CustomException e) { // error code is error.reason.null
Assert.assertSame("error.reason.null", e.getInformationCode());
}
}
But with use of #Rule, I am doing following :
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void checkNullObject() throws CustomException {
exception.expect(CustomException .class);
exception.expectMessage("Input object is null.");
MyClass myClass= null;
MyCustomClass.get(null);
}
But, I want to do something like below:
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void checkNullObject() throws CustomException {
exception.expect(CustomException .class);
//currently below line is not legal. But I need to check errorcode.
exception.errorCode("error.reason.null");
MyClass myClass= null;
MyCustomClass.get(null);
}
You can use a custom matcher on the rule with the expect(Matcher<?> matcher) method.
For example:
public class ErrorCodeMatcher extends BaseMatcher<CustomException> {
private final String expectedCode;
public ErrorCodeMatcher(String expectedCode) {
this.expectedCode = expectedCode;
}
#Override
public boolean matches(Object item) {
CustomException e = (CustomException)item;
return expectedCode.equals(e.getInformationCode());
}
}
and in the test:
exception.expect(new ErrorCodeMatcher("error.reason.null"));
You can also see how the expect(Matcher<?> matcher) has been used within ExpectedException.java source
private Matcher<Throwable> hasMessage(final Matcher<String> matcher) {
return new TypeSafeMatcher<Throwable>() {
#Override
public boolean matchesSafely(Throwable item) {
return matcher.matches(item.getMessage());
}
};
}
public void expectMessage(Matcher<String> matcher) {
expect(hasMessage(matcher));
}
I am writing a test case where in I want to run a one DataPoint for one test case and second DataPoint for second test case.
#RunWith(Theories.class)
public class DummyTest {
#DataPoints
public static String[] getFileNames() {
return new String[] { "firstFile.txt","firstFile1.txt" };
}
#Theory
public void test1(String fileName) throws Exception {
System.out.println(fileName);
assertThat(true, is(equalTo(Boolean.TRUE)));
}
#DataPoints
public static String[] getSecondFileNames() {
return new String[] { "secondFile.txt","secondFile1.txt" };
}
#Theory
public void test2(String fileName) throws Exception {
System.out.println(fileName);
assertThat(true, is(equalTo(Boolean.TRUE)));
}
}
I want that for first test case my first datapoints i.e. getFileNames method is called and for second test case getSecondFileNames datapoints should be called. Can anybody suggest is this feasible?
Thanks,
Shekhar
As of the shortly-upcoming JUnit 4.12, you can now name sets of datapoints and require parameters to come only from that set, e.g.:
#RunWith(Theories.class)
public class DummyTest {
#DataPoints("fileNames1")
public static String[] getFileNames() {
return new String[] { "firstFile.txt","firstFile1.txt" };
}
#Theory
public void test1(#FromDataPoints("fileNames1") String fileName) throws Exception {
System.out.println(fileName);
assertThat(true, is(equalTo(Boolean.TRUE)));
}
#DataPoints("fileNames2")
public static String[] getSecondFileNames() {
return new String[] { "secondFile.txt","secondFile1.txt" };
}
#Theory
public void test2(#FromDataPoints("fileNames2") String fileName) throws Exception {
System.out.println(fileName);
assertThat(true, is(equalTo(Boolean.TRUE)));
}
}
This should exactly solve your problem :-).
You could implement your own ParameterSupplier, as explained here: http://blog.schauderhaft.de/2010/02/07/junit-theories/
Tests can be grouped into "fixtures", where a fixture is a set of code that shares the same setup. Put the tests for cases using the same datapoints together in the same class, so you have one class for each set of data.
Have you looked at JUnitParams? If you just want to pass parameters to methods, which is all that your example shows, it's a much cleaner option.
#RunWith(JUnitParamsRunner.class)
public class DummyTest {
public static String[] getFileNames() {
return new String[] { "firstFile.txt","firstFile1.txt" };
}
#Theory
public void test1(String fileName) throws Exception {
System.out.println(fileName);
assertThat(true, is(equalTo(Boolean.TRUE)));
}
#DataPoints
public static String[] getSecondFileNames() {
return new String[] { "secondFile.txt","secondFile1.txt" };
}
#Theory
public void test2(String fileName) throws Exception {
System.out.println(fileName);
assertThat(true, is(equalTo(Boolean.TRUE)));
}
}