Java 在JUnit测试中使用常量或字段
在编写单元测试时,我一直遇到同一个问题。考虑下面的类:Java 在JUnit测试中使用常量或字段,java,junit,Java,Junit,在编写单元测试时,我一直遇到同一个问题。考虑下面的类: class Dog { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() {
class Dog {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class MyTest {
private static final Dog DOG = createDog();
private static final String DOG_NAME = "rex";
private static final int DOG_AGE = 3;
private static Dog createDog() {
Dog dog = new Dog();
dog.setName(DOG_NAME);
dog.setAge(DOG_AGE);
return dog;
}
@Test
public void testName() throws Exception {
SomeObject outcome = classUnderTest.doSomething(DOG);
assertThat(outcome.getName(), is(DOG_NAME));
assertThat(outcome.getAge(), is(DOG_AGE));
}
}
public class MyTest2 {
private static final String DOG_NAME = "rex";
private static final int DOG_AGE = 3;
private Dog dog;
@Before
public void setUp() {
dog = createDog();
}
@Test
public void testName() throws Exception {
SomeObject outcome = classUnderTest.doSomething(DOG);
assertThat(outcome.getName(), is(DOG_NAME));
assertThat(outcome.getAge(), is(DOG_AGE));
}
private Dog createDog() {
Dog dog = new Dog();
dog.setName(DOG_NAME);
dog.setAge(DOG_AGE);
return dog;
}
}
把狗当作一个恒量还是作为一块田来抓比较好?如果这个问题只是基于意见,我将关闭它。这是运行测试时的常见模式。。。你需要数据!有几个选择
- 复制粘贴(如您所示)
- 模式
- 或者是甜美的图案
现在,回答您的问题:这种模式的结果是,在测试中很少需要数据作为常量。您希望使测试尽可能明确,而不是添加间接层。。。因此,答案既不是常数也不是字段,而是测试本身的局部变量。如果你的狗是可变的(它有设置器),它就不是常数。我更愿意将其设置为局部变量,因为将其作为成员变量(静态或其他)意味着您可能会意外地将状态挂起,而您并不打算使用它。嗯,每次测试之前都会调用setUp方法get,所以我不能在这种状态下运行。@AndyTurner普遍同意。但是JUnit在每个测试方法之前创建测试类的新实例,并在每个测试方法之前调用setUp()方法。因此,状态,即使存储为字段,也只能通过单个测试方法使用。这是创建通用测试夹具的经典方法。使用静态可变状态是错误的,因为测试的顺序可能会改变结果:测试不再是独立的。是的,但我将其设置为静态最终字段@JBNizet如果它是最终的,他们怎么能改变它呢?如果你得到的不仅仅是一个测试,需要同一只狗呢。你会在每个测试中创建/构建这只狗作为局部变量吗?@Chris311是的,这就是想法。我假设每个测试都需要一个稍微不同的Dog实例,因此您可以在测试中定制实例。如果我查看您发布的代码,使用此模式将添加一个类(构建器)并删除测试类中的所有内容,除了用
@test
注释的实际方法。好的,考虑以下情况:您想喂狗。所以你模仿了一个叫做feeder.feed(狗,食物)的方法。你想用同样的食物喂不同的狗。所以食物永远不会改变。假设会有一个FoodBuilder。你如何定义食物?还是每个测试的局部变量?@Chris311我想在这种情况下,我会在每个测试中实例化狗(因为它们不同),对于食物,我可能会将其设置为测试的属性,但我并不完全喜欢这个想法(因为它引入了一层间接性,这意味着测试更难理解)。如果这感觉很难做到,它可能是指向一个设计问题。。。只要提到测试有助于发现设计问题就好了:)。有时候,间接层并不是一件坏事。有时,如果哪种狗粮无关紧要,你只需给一种恒定的狗粮命名即可。