Passing JUnit data between tests - java

I just discovered when creating some CRUD tests that you can't set data in one test and have it read in another test (data is set back to its initialization between each test).
All I'm trying to do is (C)reate an object with one test, and (R)ead it with the next. Does JUnit have a way to do this, or is it ideologically coded such that tests are not allowed to depend on each other?

Well, for unit tests your aim should be to test the smallest isolated piece of code, usually method by method.
So testCreate() is a test case and testRead() is another. However, there is nothing that stops you from creating a testCreateAndRead() to test the two functions together. But then if the test fails, which code unit does the test fail at? You don't know. Those kind of tests are more like integration test, which should be treated differently.
If you really want to do it, you can create a static class variable to store the object created by testCreate(), then use it in testRead().
As I have no idea what version of Junit you talking about, I just pick up the ancient one Junit 3.8:
Utterly ugly but works:
public class Test extends TestCase{
static String stuff;
public void testCreate(){
stuff = "abc";
}
public void testRead(){
assertEquals(stuff, "abc");
}
}

JUnit promotes independent tests. One option would be to put the two logical tests into one #Test method.
TestNG was partly created to allow these kinds of dependencies among tests. It enforces local declarations of test dependencies -- it runs tests in a valid order, and does not run tests that depend on a failed test. See http://testng.org/doc/documentation-main.html#dependent-methods for examples.

JUnit is independent test. But, If you have no ways, you can use "static" instance to store it.
static String storage;
#Test
public void method1() {
storage = "Hello"
}
#Test
public void method2() {
Assert.assertThat(something, is(storage));
}

How much processing time do these tests take? If not a lot, then why sweat it. Sure you will create some object unnecessarily, but how much does this cost you?
#Test
void testCreateObject() {
Object obj = unit.createObject();
}
#Test
void testReadObject() {
Object obj = null;
try {
obj = unit.createObject(); // this duplicates tests aleady done
} catch (Exception cause) {
assumeNoException(cause);
}
unit.readObject(obj);
}

in this basic example, the variable is changed in the test A, and can be used in the test B
public class BasicTest extends ActivityInstrumentationTestCase2 {
public BasicTest() throws ClassNotFoundException {
super(TARGET_PACKAGE_ID, launcherActivityClass);
}
public static class MyClass {
public static String myvar = null;
public void set(String s) {
myvar = s;
}
public String get() {
return myvar;
}
}
private MyClass sharedVar;
#Override
protected void setUp() throws Exception {
sharedVar = new MyClass();
}
public void test_A() {
Log.d(S,"run A");
sharedVar.set("blah");
}
public void test_B() {
Log.d(S,"run B");
Log.i(S,"sharedVar is: " + sharedVar.get());
}
}
output result is:
run A
run B
sharedVar is: blah

Related

Mocking Java Constant variables (public static) using Mockito/JUnit

I need to mock the constant variable in order to test one of my method. How can I do it with Mokito and Junit.
#Component( "mybean" )
#org.springframework.context.annotation.Scope( value="session" )
public class MyBean {
Public void methodToBeTested() {
if (!AppConst.SOME_CONST.equals(obj.getCostCode())) {
// some logic
}
}
}
AppConst class
#Configuration
public class AppConst
{
public static String SOME_CONST;
public static String HOST_URL;
#PostConstruct
public void postConstruct()
{
SOME_CONST = "My Code";
HOST_URL = "Some URL";
}
}
So, from my junit test class, how can I mock the AppConst and it's variables? Now, when I run it, i hit a nullpointer error.
Can this be done with powermock? if yes please give some sample
Mockito version I use.
compile "org.mockito:mockito-all:1.9.5"
compile "org.powermock:powermock-mockito-release-full:1.6.1"
Instead of mocking there would be another solution to be able to test it:
public void methodToBeTested(SomeObject obj) {
performLogic(AppConst.SOME_CONST, obj);
}
boolean performLogic(String check, SomeObject testObj) {
if (!check.equals(obj.getCostCode())) {
// some logic
return true;
}
return false;
}
That way you can test two things, both combined show you that your code works as intended:
public void testMethodToBeTested() {
MyBean mb = new MyBean() {
#Override
void performLogic(String check, SomeObject testObj) {
assertSame("check constant is passed", AppConst.SOME_CONST, check);
}
}
mb.methodToBeTested(new SomeObject());
mb = new MyBean();
SomeObject so = createSomeTestObject("My Code"); // not the actual constant but an equal String
assertFalse("check some logic not occurred", mb.performLogic("My Code", so));
so = createSomeTestObject("Not the constant");
assertFalse("check some logic not occurred", mb.performLogic("Not the constant", so));
assertTrue("check some logic occurred", mb.performLogic("My Code", so));
// additional tests covering the actual logic
}
Another solution could be putting the condition of the if-statement into its own method, e.g. shouldLogicOccurr(String check) and test that method individually.
In other words: Sometimes it's necessary to refactor your code to make tests easier or sometimes even possible at all. A good side effect is the next time you implement something you already have testability in mind and create your code suitable for this in the first place.
Mocking is a good way to get things under test that use third party libraries that can't be changed and have too many dependencies to be set up but if you end up using that for your own code you've got a design issue.

Spring boot Unit test about best practics and currectli writing tests

I want start write unit test in my project. I tried make this many times. And he always quit, because he could not understand the meaning. because I can not find and form knowledge into a single whole. I read many articles, saw many examples, and they are all different. As a result, I understand why I need write tests, I understand how to write them, but I do not understand how correctly. And I do not understand how to write them so that they are useful. I have some questions:
For example I have service:
#Service
public class HumanServiceImpl implements HumanService {
private final HumanRepository humanRepository;
#Autowired
public HumanServiceImpl(HumanRepository humanRepository) {
this.humanRepository = humanRepository;
}
#Override
public Human getOneHumanById(Long id) {
return humanRepository.getOne(id);
}
#Override
public Human getOneHumanByName(String firstName) {
return humanRepository.findOneByFirstName(firstName);
}
#Override
public Human getOneHumanRandom() {
Human human = new Human();
human.setId(Long.parseLong(String.valueOf(new Random(100))));
human.setFirstName("firstName"+ System.currentTimeMillis());
human.setLastName("LastName"+ System.currentTimeMillis());
human.setAge(12);//any logic for create Human
return human;
}
}
And I tried write Unit test for this service:
#RunWith(SpringRunner.class)
public class HumanServiceImplTest {
#MockBean(name="mokHumanRepository")
private HumanRepository humanRepository;
#MockBean(name = "mockHumanService")
private HumanService humanService;
#Before
public void setup() {
Human human = new Human();
human.setId(1L);
human.setFirstName("Bill");
human.setLastName("Gates");
human.setAge(50);
when(humanRepository.getOne(1L)).thenReturn(human);
when(humanRepository.findOneByFirstName("Bill")).thenReturn(human);
}
#Test
public void getOneHumanById() {
Human found = humanService.getOneHumanById(1L);
assertThat(found.getFirstName()).isEqualTo("Bill");
}
#Test
public void getOneHumanByName() {
Human found = humanService.getOneHumanByName("Bill");
assertThat(found.getFirstName()).isEqualTo("Bill");
}
#Test
public void getOneHumanRandom() {
//???
}
}
I have questions:
1. Where should I fill the objects? I saw different implementations
in #Before like in my example, in #Test, mix implementations - when Human create in #Before and expression
when(humanRepository.getOne(1L)).thenReturn(human);
in #Test method
private Human human;
#Before
public void setup() {
human = new Human();
...
}
#Test
public void getOneHumanById() {
when(humanRepository.getOne(1L)).thenReturn(human);
Human found = humanService.getOneHumanById(1L);
assertThat(found.getFirstName()).isEqualTo("Bill");
}
2. How can I test getOneHumanRandom() method?
Service not use repository when call this method. I can make this method mock, but what will it give?
when(humanService.getOneHumanRandom()).thenReturn(human);
...
#Test
public void getOneHumanRandom() {
Human found = humanService.getOneHumanRandom();
assertThat(found.getFirstName()).isEqualTo("Bill");
}
I just copy the logic from the service in the test class. What is the point of such testing and is it necessary?
1. Where should I fill the objects? I saw different implementations
I would use #Before for any common setup between all / most tests. Any setup that is specific to a certain test should be go into that test method. If there is a common setup between some, but not all, of your tests you can write private setup method(s).
Remember to keep your tests / code DRY (dont repeat yourself!). Tests have a maintenance factor and keeping common code together with help alleviate some headaches in the future.
2. How can I test getOneHumanRandom() method?
You should create a Human toString() method. This method should concat all the properties on your Human object. You can call getOneHumanRandom() twice and assert that they are not equal.
#Test
public void getOneHumanRandomTest()
{
// SETUP / TEST
Human one = service.getOneHumanRandom();
Human two = service.getOneHumanRandom();
// VERIFY / ASSERT
assertNotEquals("these two objects should not be equal", one.toString(), two.toString())
}
Hope this helps!

Execute order for test suite in junit

I am having a test suite which is having the following structure
TestClass1
- testmethod1()
- testmethod2()
- testmethod3()
- testmethod4()
TestClass2
- testmethod11()
- testmethod22()
- testmethod33()
- testmethod44()
In the above structure i want to execute the testmethod4() as the final one. ie) executed at last.
There is a annotation #FixMethodOrder which executes a method in order not the testclass. Is there any mechanism to maintain order in test class and testmethod together. With the #FixMethodOrder i can execute the method by renaming the name of the test method but i can't instruct junit to execute the test class as the final one(last one).
Though quoting #Andy again -
You shouldn't care about test ordering. If it's important, you've got
interdependencies between tests, so you're testing behaviour +
interdependencies, not simply behaviour. Your tests should work
identically when executed in any order.
But if the need be to do so, you can try out Suite
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestClass2.class,
TestClass1.class
})
public class JunitSuiteTest {
}
where you can either specify
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestClass1 {
#AfterClass
public void testMethod4() {
and then take care to name your method testMethod4 as such to be executed at the end OR you can also use #AfterClass which could soon be replaced by #AfterAll in Junit5.
Do take a look at Controlling the Order of the JUnit test by Alan Harder
#shiriam as #Andy Turner already pointed out, the order of your tests shouldn't come in question when running the tests.
If you have a routine that you want executed before doing any tests, you could use a static block of code in one of the classes.
Think of something like this:
class TestBootstrap {
// singleton instance
private static final instance;
private boolean initialized;
private TestBootstrap(){
this.initialized = false;
}
public static TestBootstrap getInstance(){
if (instance == null){
instance = new TestBootstrap()
}
}
public void init(){
// make the method idempotent
if (!initialzed){
// do init stuff
initialized = true;
}
}
public boolean isInitialized(){
return initialized;
}
}
Then in your tests use something like this:
class TestClass1{
#BeforeClass
public void setup(){
TestBootstrap.getInstance().init();
}
#Test
public void testmethod1(){
// assertions
}
// ....
}
class TestClass2{
#BeforeClass
public void setup(){
TestBootstrap.getInstance().init();
}
#Test
public void testmethod11(){
// assertions
}
// ...
}
By using the singleton instance for doing the setup for the tests you ensure that you perform the initialization of your test environment only once, independently of the order in which the test classes are executed.

TestNG dataproviders with a #BeforeClass

I am trying to run a class with multiple tests under two different conditions. Basically I have a bunch of tests related to a search. I am adding new functionality of a new search strategy, and in the meantime want to run the already written tests under both configurations. As we have multiple classes each with multiple tests I want to streamline this process as much as possible. Ideally it'd be great to do the setup in a #BeforeClass with a data provider so that all tests in the class are basically run twice under the different configurations, but doesn't look like this is possible.
Right now I have:
public class SearchTest1 {
#Test(dataProvider = "SearchType")
public void test1(SearchType searchType) {
setSearchType(searchType);
//Do the test1 logic
}
#Test(dataProvider = "SearchType")
public void test2(SearchType searchType) {
setSearchType(searchType);
//Do the test2 logic
}
#DataProvider(name = "SearchType")
public Object[][] createData() {
return new Object[][]{
new Object[] {SearchType.scheme1, SearchType.scheme2}
}
}
}
Is there a better way to do this?
If you want to avoid having to annotate each and every method with the data provider, you can use a Factory instead.
public class SearchTest1 {
private final SearchType searchType;
public SearchTest1( SearchType searchType ) {
this.searchType = searchType;
}
#Test
public void test2() {
//Do the test2 logic
}
...
}
And your factory class will be:
public class SearchTestFactory {
#Factory
public Object [] createInstances() {
return new Object[] { new SeartchTest1( SearchType.ONE ), new SearchTest1( SearchType.TWO ) };
}
}
See more on this here.
Then you can either have one factory that enumerates every test class or a separate factory for each, the first one is obviously less flexible, the second one means slightly more code.
You can use parameters in #BeforeClass. Just use (with some cleanup)
context.getCurrentXmlTest().getParameters()
#SuppressWarnings("deprecation")
#BeforeClass
public void setUp(ITestContext context) {
System.out.println(context.getCurrentXmlTest().getAllParameters());
}

JUnit tests in files

I used to write JUnit tests as methods, such as:
public class TextualEntailerTest {
#Test test1() {...}
#Test test2() {...}
#Test test3() {...}
}
Since most of the test cases has a similar structure, I decided to be "data-driven", and put the contents of the tests in XML files. So, I created a method "testFromFile(file)" and changed my test to:
public class TextualEntailerTest {
#Test test1() { testFromFile("test1.xml"); }
#Test test2() { testFromFile("test2.xml"); }
#Test test3() { testFromFile("test3.xml"); }
}
As I add more and more tests, I become tired of adding a line for each new test file I add. Of course I can put all files in a single test:
public class TextualEntailerTest {
#Test testAll() {
foreach (String file: filesInFolder)
testFromFile(file);
}
}
However, I prefer that each file will be a separate test, because this way JUnit gives nice statistics about the number of files passed and failed.
So, my question is: how to tell JUnit to run separate tests, where each test is of the form "testFromFile(file)", for all files in a given folder?
You could use Theories where the files are #DataPoints so you won't need to loop in your test and will allow for setup and cleanup after each file. But it will still be reported as such.
Theories also have the issue that they fail fast (quit after first failure) as your test above does. I find that this is not good practice since it can hide a situation where you have multiple bugs. I recommend using seperate tests or use the loop with an ErrorCollector. I really wish Theories had ErrorCollector built in.
Not sure, but may be these can help you.
Reference1 Reference2. Hope this helps.
#RunWith(value = Parameterized.class)
public class JunitTest {
private String filename;
public JunitTest(String filename) {
this.filename= filename;
}
#Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] { { "file1.xml" }, { "file2.xml" } };
return Arrays.asList(data);
}
#Test
public void Test() {
System.out.println("Test name:" + filename);
}
}

Categories