I have a test with 15-20 different test cases, I want to run the same test with twice with two different parameters which are supposed to be passed to the test's BeforeClass method, for instance:
public class TestOne {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument1", "Argument2");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here
}
public class TestTwo {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here, same as in TestOne
}
As you can see the only difference between these two tests is in the setup method, which passes different values to the constructor of the ClassToTest. I don't want to replicate the test methods in both classes, but would prefer either inheritance or some other intelligent way to achieve this in one class.
This seems like a perfect use case for JUnit4's #Parameters; see https://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit or http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/ . That said, you'll have to move the initialization from the setUp method to a constructor for the test class.
For what it's worth, here is how you would do it with TestNG:
public class TestFactory {
#Factory
public Object[] createTests() {
return new Object[] {
new ClassToTest("arg1", "arg2"),
new ClassToTest("arg3", "arg4")
};
}
}
public class ClassToTest {
public ClassToTest(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
#Test
public void testOne() {
// use arg1 and arg2
}
}
Thanks all for your quick replies. This is how I did it finally
public abstract class Base {
final HeavyObject heavy;
protected Base(HeavyObject heavy) {
this.param = param;
}
#Test
public void test() {
param.doSomething();
}
#Test
.............More tests here
}
public class FirstTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg1", "arg2");
}
public FirstTest() {
super(param);
}
}
public class SecondTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg3", "arg4");
}
public FirstTest() {
super(param);
}
}
Base is an abstract class which has all the tests and FirstTest and SecondTest create their own objects with different parameters and pass it to the abstract class to use it.
As per the documentation (http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html):
A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for
accessing its private fields, these can also be used by the subclass.
How about this:
public class TestOne {
private static ClassToTest classToTest1, classToTest2;
#BeforeClass
public static void setUp() throws Exception {
classToTest1 = new ClassToTest("Argument1", "Argument2");
classToTest2 = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
testOneImpl(classToTest1);
testOneImpl(classToTest2);
}
public void testOneImpl(ClassToTest classToTest) {
// exact samew as whatever your current testOne() test method is
}
....
}
EDIT:
Or to keep method count down:
public class TestOne {
private static List<ClassToTest> classesToTest;
#BeforeClass
public static void setUp() throws Exception {
classesToTest = new ArrayList<>;
classesToTest.add( new ClassToTest("Argument1", "Argument2"));
classesToTest.add( new ClassToTest("Argument3", "Argument4"));
}
#Test
public void testOne() {
for (ClassToTest classToTest: classesToTest) {
... same test content as before
}
}
Related
I want to test that fan.setState method is called or not
class OffState implements State {
#Override
public void changeState(Fan fan) {
fan.setState(new OnState());
}
}
Like this:
#RunWith(MockitoJUnitRunner.class)
public class OffStateTest {
#Mock
private Fan fan;
#Test
public void testChangeState() {
//Arrange
OffState offState = new OffState();
//Act
offState.changeState(fan);
//Assert
Mockito.verify(fan).setState(Mockito.any(OnState.class));
}
}
I have the following class to test.
public class ClassToTest {
private View view;
public ClassToTest(View view) {
this.view = view;
}
public void init() {
view.add(new ParamClass.OnSomething() {
#Override
public void onSomethingElse() {
view.doSomeWork();
}
});
}
}
Where view is
public class View {
public void add(OnSomething onSomething) {
}
public void doSomeWork() {
}
}
I have mocked view object, but no clue how to test the logic marked "Some logic here to test"
ParamClass is final.
public final class ParamClass {
public interface onSomething {
public void onSomethingElse();
}
}
Without making change to source, is there a way to unit test this using Mockito / Powermockito?
I'm trying to verify the invocation of doSomeWork()
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ClassToTest.class })
public class TestClass {
#Mock View view;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
ClassToTest classToTest = new ClassToTest(view);
PowerMockito.doCallRealMethod().when(view).add(Mockito.any(ParamClass.OnSomething.class));
PowerMockito.whenNew(ParamClass.OnSomething.class)
.withAnyArguments()
.thenReturn(new ParamClass.OnSomething() {
#Override
public void onSomethingElse() {
view.doSomeWork();
}
});
classToTest.init();
Mockito.verify(view, Mockito.times(1)).doSomeWork();
}
}
Its throwing exception
java.lang.ArrayIndexOutOfBoundsException: 0
at org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup.withAnyArguments(DefaultConstructorExpectationSetup.java:66)
at com.linkedin.android.lite.animations.TestClass.test(TestClass.java:29)
I figured out how to do it. Updating the answer.
public class TestClass {
#Mock View view;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
ClassToTest classToTest = new ClassToTest(view);
classToTest.init();
ArgumentCaptor<ParamClass.OnSomething> captor =
ArgumentCaptor.forClass(ParamClass.OnSomething.class);
verify(view).add(captor.capture());
ParamClass.OnSomething onSomething = captor.getValue();
onSomething.onSomethingElse();
Mockito.verify(view, Mockito.times(1)).doSomeWork();
}
}
Well what are you exactly trying to test? If there is code inside onSomethingElse that calls other objects/methods then you can simply mock all those other calls and then use Mockito.verify(mockObjectHere).methodCalled() on those methods that were called, if you just want to implement testing for behaviour.
I have a class to be tested which is like this:
public class MainClass extends BaseClass {
public static int variableToBeAsserted= 0;
MainClass(ConfigClass config) {
super(config);
}
public void myMethod() {
List list = objectOfClass1inSuperClass.operation(objectOfClass2inSuperClass.method())
while(methodInSuperClass()) {
// doing operations with 'list'
variableToBeAsserted++;
}
}
// ..few other methods which I am not going to test.
}
I have suppressed the constructor of my BaseClass and my ConfigClass. Now my test class is like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class TestClass {
#Before
public void setUp(){
suppress(constructor(BaseClass.class))
suppress(constructor(ConfigClass.class))
}
#Test
public void testMyMethod(){
MainClass main = new MainClass(new ConfigClass(""));
List list1= new ArrayList();
test1.add("somevalues");
Class1inSuperClass ob1 = PowerMock.createMock(Class1inSuperClass.class);
Class2inSuperClass ob2 = PowerMock.createMock(Class2inSuperClass.class);
EasyMock.expect(ob2.method()).andReturn(getClass());
EasyMock.expect(ob1.operation(getClass())).andReturn(list1);
PowerMock.replayAll();
main.myMethod();
Assert.assertEquals(expectedValue, main.variableToBeAsserted);
}
}
Now I don't know why but my test case fails with a NullPointerException.
It tries to access objectofClass1inSuperClass and fails. I thought this will mock it. But it does not get mocked.
EDIT: I am writing only the test and I cannot change anything in BaseClass. However I have the option to modify the MainClass.
You have two ways to inject mock object to the object under the test.
Manually via WhiteBox
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class WhiteBoxApproachTestClass {
#Before
public void setUp() throws Exception {
suppress(constructor(BaseClass.class));
}
#Test
public void testMyMethod() {
MainClass main = new MainClass(createMock(ConfigClass.class));
List<String> list1 = new ArrayList<>();
list1.add("somevalues");
Class1inSuperClass ob1 = createMock(Class1inSuperClass.class);
Class2inSuperClass ob2 = createMock(Class2inSuperClass.class);
expect(ob2.method()).andReturn(getClass());
expect(ob1.operation(getClass())).andReturn(list1);
Whitebox.setInternalState(main, "objectOfClass1inSuperClass", ob1);
Whitebox.setInternalState(main, "objectOfClass2inSuperClass", ob2);
replayAll();
main.myMethod();
assertThat(MainClass.variableToBeAsserted).isEqualTo(5);
}
}
And via #TestSubject (http://easymock.org/user-guide.html#mocking-annotations)
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class TestSubjectApproachTestClass {
#Mock(fieldName = "objectOfClass1inSuperClass")
private Class1inSuperClass ob1;
#Mock(fieldName = "objectOfClass2inSuperClass")
private Class2inSuperClass ob2;
#TestSubject
private final MainClass main = new MainClass(createMock(ConfigClass.class));
#BeforeClass
public static void before() throws Exception {
suppress(constructor(BaseClass.class));
}
#Test
public void testMyMethod() {
List<String> list1= new ArrayList<>();
list1.add("somevalues");
expect(ob2.method()).andReturn(getClass());
expect(ob1.operation(getClass())).andReturn(list1);
EasyMockSupport.injectMocks(main);
replayAll();
main.myMethod();
assertThat(MainClass.variableToBeAsserted).isEqualTo(5);
}
}
Full code you may find here.
I try to use different instances for my tests but the first one is always used.
During the second test, it's the content of the first instance that is displayed.
I don't know where to look for.
public class MyActivityTest extends
ActivityInstrumentationTestCase2<MyActivity> {
private Solo solo;
public MyActivityTest() {
super(MyActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
Authentication.setSessionId("mysessionid", this.getInstrumentation()
.getTargetContext().getApplicationContext());
solo = new Solo(getInstrumentation(), getActivity());
}
public void testFailFetching() {
CommunicationFactory.setInstance(MyActivityData.FALSE_QUIZCOMM_DEFAULT);
//some Solo tests
}
public void testSucceedFetching() {
CommunicationFactory.setInstance(MyActivity.CORRECT_QUIZCOMM_DEFAULT);
//some Solo tests
}
#Override
protected void tearDown() throws Exception {
CommunicationFactory.setInstance(null);
super.tearDown();
}
}
The setUp() method will be called before each test. Provided it completes without throwing an exception (which presumably would abort your tests anyway), your solo variable is being reconstructed for each test. The follow test code demonstrates this:
public class ExampleTest extends TestCase {
private static int num = 1;
private Foo foo;
#Override
protected void setUp() throws Exception {
super.setUp();
foo = new Foo(num++);
}
public void testA() {
foo.printNum();
}
public void testB() {
foo.printNum();
}
private static class Foo {
private final int num;
public Foo(int num) {
this.num = num;
}
public void printNum() {
System.out.println(num);
}
}
}
This prints:
1
2
It's possible the Solo objects equal each other in the separate tests. But they won't be the same object.
So right now I'm using JUnit 4 and in the #BeforeClass methods I setup everything needed to reset the user schema or to prepare sample data.
Now, it's not that I don't like this approach but I found it quite frustrating for the following reason:
I'm using the Parameterized annotation to run the very same tests with different input data. Parameterized doesn't work on #BeforeClass because #BeforeClass works with a static method.
This means I have to replicate tests if I want to keep the #BeforeClass logic. I can't use #After and #Before because those will happen after every test and it would be an overhead.
I was thinking I could refactor this Unit Tests in the sense that I'll write an abstract class that handles the test and a subclass for every group parameters I want to try so that I can have the test code written only once.
I'm hoping you can suggest a cleaner option with the following starting point: the use of #Parameterized, the need to run the "database" method only once per parameter group.
EDIT:
this is an example of my class without the BeforeClass
RunWith(LabelledParameterized.class)
public class TestCreateCampaign extends AbstractTestSubscriberCampaign {
public TestCreateCampaign(String label, String apiKey, String userKey,
int customerId) {
super(label, apiKey, userKey, customerId);
}
#Before
public void setUp() throws Exception {
super.setUp();
}
#After
public void tearDown() throws Exception {
super.tearDown();
}
#Parameters
public static Collection<Object[]> generatedData() {
return DataProvider.generatedCorrectSubscriberData();
}
#Test
public void testCreateEmailCampaignBothTriggered() {
// TEST
}
#Test
public void testCreateTextCampaignTriggered() {
// TEST
}
#Test
public void testCreateTextCampaignTest() {
// TEST
}
// Other Tests
}
This depends on how you want to set up your classes, but you can use a ClassRule for this. This does the same job as a TestRule, but it runs once for each class, rather than each test. This can be combined with Parameterized and TestRule, such as:
#RunWith(Parameterized.class)
public class TestCreateCampaign {
#ClassRule
public static ExternalResource beforeAfterClass = new ExternalResource() {
#Override
protected void before() throws Throwable {
System.out.println("before each class");
}
#Override
protected void after() {
System.out.println("after each class");
}
};
#Rule
public ExternalResource beforeAfter = new ExternalResource() {
#Override
protected void before() throws Throwable {
System.out.println("before each test");
}
#Override
protected void after() {
System.out.println("after each test");
}
};
#Parameters(name = "{index}: fib({0})={1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 3, 0 }, { 4, 1 } });
}
private int fInput;
private int fExpected;
public TestCreateCampaign(int input, int expected) {
fInput = input;
fExpected = expected;
}
#Test
public void test1() {
System.out.println("test1 fInput=" + fInput);
}
}
This produces the following output:
before each class
before each test
test1 3
after each test
before each test
test1 4
after each test
after each class
This seems to be what you're looking for. To cut down on the amount of duplication, you can of course define beforeAfterClass and beforeAfter in a separate java class.
These are available in JUnit 4.9+.
What about calling your setup method from the constructor of your parameterized test class?
Edit:
OK, do I don't know of anything that does this automatically, but I think you could code up a Rule to do it. You could either implement a Rule from scratch of extend ExternalResource. Here is what I think it would do.
The constructor would take an instance of the test class and an ExternalResource instance.
In the constructor it would find the list of methods that contain the #Test annotation a get a count. It would set an iteration count to 0.
In the before method it would increment the iteration count and if it is 1 after increment (or 0 before) it would invoke the before method on the passed ExternalResource.
In the after method it would check to see if the iteration count was equal to the number of tests and if so call the after method on the passed ExternalResource.
You might need to use a different callback class / interface and ExternalResource since the before and after methods are protected. If you really wanted to be cool, you would define your own BeforeParameters and AfterParameter annotations in your rule and it would look for those methods in the passed instance.
If you develop this please post it or submit it to JUnit for inclusion.
Here is what I came up with, not as nice as I would like:
#RunWith(Parameterized.class)
public class TestExample {
private interface BeforeAfter {
void before();
void after();
}
public static class Resource extends ExternalResource {
private final int count;
private final BeforeAfter ba;
private int iteration = 0;
Resource(Object instance, BeforeAfter ba) {
int localCount = 0;
for (Method method : instance.getClass().getMethods()) {
if (method.getAnnotation(Test.class) != null) {
localCount++;
}
}
this.count = localCount;
this.ba = ba;
}
#Override
protected void before() throws Throwable {
if (iteration == 0) {
ba.before();
}
iteration++;
}
#Override
protected void after() {
if (iteration == count) {
ba.after();
iteration = 0;
}
}
}
#Parameters
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 3, 0 }, { 4, 1 } });
}
#Rule
public static Resource resource = new Resource(new TestExample(0, 0), new BeforeAfter() {
#Override
public void before() {
System.out.println("setup");
}
#Override
public void after() {
System.out.println("cleanup");
}
});
private int fInput;
private int fExpected;
public TestExample(int input, int expected) {
// System.out.println("Constructor invoked" + fInput);
fInput = input;
fExpected = expected;
}
#Test
public void test1() {
System.out.println("test1 fInput=" + fInput);
}
#Test
public void test2() {
System.out.println("test2 fInput=" + fInput);
}
}
Resulted in:
setup
test1 fInput=3
test2 fInput=3
cleanup
setup
test1 fInput=4
test2 fInput=4
cleanup
See How to load DBUnit test data once per case with Spring Test for a way of initialising your test data only once per test run.