Java 在测试之间传递JUnit数据

Java 在测试之间传递JUnit数据,java,junit,Java,Junit,我刚刚发现,在创建一些CRUD测试时,不能在一个测试中设置数据并在另一个测试中读取(数据在每个测试之间被设置回初始化状态) 我所要做的就是(C)用一个测试创建一个对象,然后(R)用下一个测试读取它。JUnit有办法做到这一点吗?或者它是在意识形态上编码的,这样测试就不允许相互依赖吗?好吧,对于单元测试,您的目标应该是测试最小的独立代码段,通常是逐个方法。 因此,testCreate()是一个测试用例,testRead()是另一个。但是,没有任何东西可以阻止您创建一个testCreateAndRe

我刚刚发现,在创建一些CRUD测试时,不能在一个测试中设置数据并在另一个测试中读取(数据在每个测试之间被设置回初始化状态)


我所要做的就是(C)用一个测试创建一个对象,然后(R)用下一个测试读取它。JUnit有办法做到这一点吗?或者它是在意识形态上编码的,这样测试就不允许相互依赖吗?

好吧,对于单元测试,您的目标应该是测试最小的独立代码段,通常是逐个方法。 因此,
testCreate()
是一个测试用例,
testRead()
是另一个。但是,没有任何东西可以阻止您创建一个
testCreateAndRead()
来同时测试这两个函数。但是如果测试失败,测试失败的代码单元是哪一个?你不知道。这些类型的测试更像是集成测试,应该区别对待

如果确实需要,可以创建一个静态类变量来存储由
testCreate()
创建的对象,然后在
testRead()
中使用它

因为我不知道你说的Junit是什么版本,所以我只选择了古老的Junit 3.8:

非常难看,但有效:

public class Test extends TestCase{

    static String stuff;

    public void testCreate(){
        stuff = "abc";
    }

    public void testRead(){
        assertEquals(stuff, "abc");
    }
}

JUnit促进独立测试。一种选择是将两个逻辑测试放在一个@Test方法中


TestNG的创建部分是为了允许测试之间存在此类依赖关系。它强制执行测试依赖项的本地声明——它以有效的顺序运行测试,而不运行依赖于失败测试的测试。参见示例。

这些测试需要多少处理时间?如果不是很多,那为什么要汗流浃背呢。当然,您将不必要地创建一些对象,但这需要多少成本

@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);
}

在这个基本示例中,变量在测试A中更改,并且可以在测试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());        
    }

}
输出结果为:

经营

跑B


sharedVar是:blah

JUnit是独立测试。但是,如果您没有办法,可以使用“静态”实例来存储它

static String storage;
@Test
public void method1() {
    storage = "Hello"
}

@Test
public void method2() {
    Assert.assertThat(something, is(storage));
}

这就是意识形态!我很害怕。我确实认为,仔细想想,有一些新的注释必须与intertest依赖性有关,但也许我在阅读有关TestNG的文章。单元测试在状态和顺序上都是独立的非常理想。JUnit支持这个理想。TestNG支持理想的和实用的异常。TestNG的作者Cedric Beust在下面的资料中更详细地讨论了这些问题。他与Beck和Gamma确认了JUnit的意图,并发现了与静态成员一起使用JUnit方法的缺点。*Beust 2004年的博文*Beust的书《下一代Java测试:TestNG和高级概念》的前几页,Addison Wesley,2008年。对于单元测试,我同意所有这些。但是CRUD测试是数据库访问,因此不是单元测试。令人遗憾的是,JUnit如此灵活和普及,应该以任何方式限制它只限于单元测试。这一点很好。相反,TestNG允许您通过“groups”属性使用测试类别(如“database”或“integration”)标记测试;提供@BeforeGroup/@AfterGroup设置/拆卸方法;并支持运行或排除运行一组组。关于Beust幻灯片6-11的更多详细信息,请参见此处:。要进行真正的CRUDy单元测试,必须设置测试状态(数据库)并在后记中将其删除。不幸的是,这通常非常复杂且容易出错,这增加了测试开发开销,同时也增加了测试失败噪音。设置状态的低错误率方法的一个例子是运行SQL脚本,而高错误率方法是使用与正在测试的方法相同的方法。不幸的是,根据项目的不同,前者几乎总是不切实际的,甚至是不可能的,因此对于后者,测试依赖性似乎解决了这个问题。更重要的是,我必须想出测试数据来确保2个createObject()中的唯一性,但这可能是一种方法。我想我有一部分人会抵制两次编写相同的“创建”代码。我觉得我太枯燥了。@orbbish这是在不引入测试之间的依赖关系的情况下你能得到的最枯燥的了@emory对
unit.readObject
的调用应在
try
块内执行。您依赖于
catch
子句的内容来避免出现
NullPointerException
之类的情况。这是一种集成测试-duh,CRUD意味着访问数据库。顺便说一句,关于静态变量的好主意,如果它有效的话。我得试试。你能保证它能用吗?您是否定义了JUnit可靠地执行这些测试的顺序?@orbbish这已经晚了6年,但是:JUnit是一个单元测试框架,而不是一个集成测试框架one@oldrinb....not现在…自从它被每个测试工具采用以来…他们添加了多个特性,使它成为一个单元和集成测试工具[这里是我提出的解决方案,并解释了使用静态变量的缺点][1][1]:@JacobKo您的链接导致页面未找到您的示例不包含“@Test注释”。我尝试了添加“@Test”的代码,但运气不佳。您尝试过这个吗?我的印象是JUnit测试必须至少包含一个这样的注释。我从最初问起就知道这样做是不好的;)