0

I have problem with passing a bean class like mvc concept to implement to jUnit class. I don't want change the structure jUnit class, because i have need it.

Class DataBean

public class DataBean {
    private String browserName;
    private String userName;

    public String getBrowserName() {
        return browserName;
    }

    public void setBrowserName(String browserName) {
        this.browserName = browserName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

Class Main

public class Main {
    public static void main(String[] args) {
        String[] arrBrowserName = {"chrome", "firefox"};
        String[] arrUserName = {"user1", "user2"};

        for(int i=0; i<2; i++) {
            DataBean dataBean = new DataBean();

            String browserName = arrBrowserName[i];
            String userName = arrUserName[i];

            dataBean.setBrowserName(browserName);
            dataBean.setUserName(userName);

            //How to call "TestCase1", include passing the "databean"
            JUnitCore junit = new JUnitCore();
            junit.run(TestCase1.class);
        }
    }
}

Class TestCase1

public class TestCase1 {
    DataBean dataBean = new DataBean();

    //Here, how to do ? i want to get "databean" from "Main" class, without change this is class as jUnit

    @Before
    public void setUp(){
        //set up based on data from "Main class"
    }

    @Test
    public void scenario(){
        //
    }

    @After
    public void tearDown(){
        //
    }
}

Based on the above code, let's say i have 2 data as data testing, i want setup the before based on the data from Main class. Where is i placement the parameter in TestCase1 so that I can get databean ? and is this possible?

frianH
  • 7,295
  • 6
  • 20
  • 45

1 Answers1

2

FYI, the DataBean object is a smell called anemic object.

It is a DTO (object to transport data), so except when required by some framework, try to keep these immutable, or at least make it explicit that there is no encapsulation:

public class DataBean {
    public String browserName;
    public String userName;
}

Anyway, it seems that you are trying to parameterize a test.

Given that the test object is built by JUnit, you will have to change the test class using the API provided by JUnit to inject the needed object/data.

You could use a ThreadLocal storage to bypass the framework API, but I do not recommand it at all.

If you use JUnit, do it the JUnit way.

Assuming that you still use JUnit4, you can go (at least) two ways:

First, using JUnit4 built-in runner Parameterized, making a test class parameterized:

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class BrowserTest {
    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][]{
                {new DataBean("chrome", "user1")},
                {new DataBean("firefox", "user2")}
        });
    }

    private final DataBean dataBean;

    public BrowserTest(DataBean dataBean) {
        this.dataBean = dataBean;
    }

    @Test
    public void test() {
        // Test using a dataBean instance
    }
}

Second, use a third library called JUnitParams with the runner JUnitParamsRunner, making a test method parameterized:

import org.junit.Test;
import org.junit.runner.RunWith;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;

@RunWith(JUnitParamsRunner.class)
public class BrowserTest {

    @Test
    @Parameters(method = "test_cases")
    public void test(DataBean dataBean) {
        // Test using a dataBean instance
    }

    public static Object[] test_cases() {
        return new Object[]{
                new DataBean("chrome", "user1"),
                new DataBean("firefox", "user2")
        };
    }
}

Finally, there is the new version, JUnit5 which changes a lot regarding its extention model as it allows composition of features (instead of having only one runner).

With JUnit5, the same test can be written like this:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class BrowserTest {

    @ParameterizedTest
    @CsvSource({
        "chrome, user1",
        "firefox, user2"
    })
    void test(String browserName, String userName) {
        // Test using a dataBean instance
    }
}

Hope this helps !

Loïc Le Doyen
  • 975
  • 7
  • 16
  • Hi @Loïc Le Doyen, sorry for delay respons. It's possible if i want passing my `dataBean` from `Main class` to your `Collection class` in @Parameters ? let's say I've change the `Databean class` to be public, not encapsulation. – frianH Nov 30 '18 at 05:53
  • Encapsulation as nothing to do with the ability to transport objects. If your need is really to take something from your main method to a test method, you can still use a public mutable singleton and make the `data` method of my first example return its value. But keep in mind, this is not the way to do it. If you have parameters of your main method(`String[] args`) that generates test cases, maybe JUnit4 is not the right fit and it may be best not using it. – Loïc Le Doyen Nov 30 '18 at 10:19
  • Thank's for the explanation – frianH Dec 02 '18 at 13:08