在不初始化 class 的情况下测试方法
Test a method without initialize the class
我是单元测试的新手,我想知道是否有一种方法可以在不初始化 class 的情况下测试方法。我问的原因是因为在构造函数中传递了很多对象,这意味着很多模拟存根,而从彻底检查来看 methodToTest
似乎没有使用任何对象属性。这不是我的代码,否则该方法可以转换为静态方法。
class ExampleClass {
public ExampleClass(FirstClass fc, SecondClass sc, ThirdClass tc) {}
public void methodToTest(FourthClass foc) {}
}
据我所知,如果不初始化 class,您将无法进行测试。
Test的三个步骤是Arrange、Act和Assert。 class 必须在安排部分初始化,以便在您正在测试的特定 class 中获取所需的方法。
您在这里有一些选择:
- 将方法设为静态,这样您就不需要引用实际对象。这仅在该方法不需要 ExampleClass 的任何状态时才有效(即它需要的一切都在方法参数中传递)。
- 将此方法提取到另一个更易于自行测试的 class(可能使用方法对象模式)。此重构称为 replace method with method object.
我不知道你的方法是做什么的,但如果你的应用程序可行,你可以将 methodToTest
设为静态,这样你就可以在没有 class 的实例的情况下调用它。
或者,您可以通过在用于所有测试的 @BeforeClass
方法中创建一个实例来避免过多的实例化,但同样我不知道您的方法做了什么,所以这可能不是理想的。
好的,看来我找到方法了。由于方法与对象的状态无关,我可以模拟对象并命令 MockRunner 在调用时使用真实的方法。它被命名为部分模拟。做法是
ExampleClass = PowerMockito.mock(ExampleClass.class);
when(ExampleClass.methodToTest(foc)).thenCallRealMethod();
通常情况下,构造函数中的参数过多是一种错误观念的暗示。您最好重新考虑对象和 classes 以减少提供给构造函数的参数。
如果您不想,您仍然可以使用某种 "TestUtil" 来为您实例化 class。
示例:
public class MyTestUtils {
public createValidFirstClass() {
return new FirstClass(/* some arguments here */);
}
public createValidSecondClass() {
return new SecondClass(/* Some arguments here */);
}
public createValidThridClass() {
return new ThridClass(/* Some arguments here */);
}
public createValidExampleClass() {
return new ExampleClass(createValidFirstClass(), createValidSecondClass(), createValidThridClass());
}
}
这个 class 必须在您的测试包中而不是在您的项目中,并且不应在测试之外使用,这将是一个非常糟糕的做法,在您的实际项目中使用 Factory 或 Builder .
无论如何,我认为最好的解决办法是重新考虑你类。
示例:
public class People {
public People(String firstName, String lastName, Date birth, Date death) {
}
}
如您所见,控制所有给定参数的格式是否正确且不为空是一件很痛苦的事情。
通过这种方式可以减少传递给方法的参数数量。
public class People {
public People(PeopleNames names, Period period) {
}
}
public class PeopleNames {
public People(String firstName, String lastName) {
}
}
public class PeopleNames {
public People(Date begin, Date end) {
}
}
使用 PowerMockito 的抑制。
import org.powermock.api.support.membermodification.MemberModifier;
import org.powermock.api.support.membermodification.MemberMatcher;
suppress(MemberMatcher.constructor(ExampleClass.class))
我是单元测试的新手,我想知道是否有一种方法可以在不初始化 class 的情况下测试方法。我问的原因是因为在构造函数中传递了很多对象,这意味着很多模拟存根,而从彻底检查来看 methodToTest
似乎没有使用任何对象属性。这不是我的代码,否则该方法可以转换为静态方法。
class ExampleClass {
public ExampleClass(FirstClass fc, SecondClass sc, ThirdClass tc) {}
public void methodToTest(FourthClass foc) {}
}
据我所知,如果不初始化 class,您将无法进行测试。
Test的三个步骤是Arrange、Act和Assert。 class 必须在安排部分初始化,以便在您正在测试的特定 class 中获取所需的方法。
您在这里有一些选择:
- 将方法设为静态,这样您就不需要引用实际对象。这仅在该方法不需要 ExampleClass 的任何状态时才有效(即它需要的一切都在方法参数中传递)。
- 将此方法提取到另一个更易于自行测试的 class(可能使用方法对象模式)。此重构称为 replace method with method object.
我不知道你的方法是做什么的,但如果你的应用程序可行,你可以将 methodToTest
设为静态,这样你就可以在没有 class 的实例的情况下调用它。
或者,您可以通过在用于所有测试的 @BeforeClass
方法中创建一个实例来避免过多的实例化,但同样我不知道您的方法做了什么,所以这可能不是理想的。
好的,看来我找到方法了。由于方法与对象的状态无关,我可以模拟对象并命令 MockRunner 在调用时使用真实的方法。它被命名为部分模拟。做法是
ExampleClass = PowerMockito.mock(ExampleClass.class);
when(ExampleClass.methodToTest(foc)).thenCallRealMethod();
通常情况下,构造函数中的参数过多是一种错误观念的暗示。您最好重新考虑对象和 classes 以减少提供给构造函数的参数。
如果您不想,您仍然可以使用某种 "TestUtil" 来为您实例化 class。
示例:
public class MyTestUtils {
public createValidFirstClass() {
return new FirstClass(/* some arguments here */);
}
public createValidSecondClass() {
return new SecondClass(/* Some arguments here */);
}
public createValidThridClass() {
return new ThridClass(/* Some arguments here */);
}
public createValidExampleClass() {
return new ExampleClass(createValidFirstClass(), createValidSecondClass(), createValidThridClass());
}
}
这个 class 必须在您的测试包中而不是在您的项目中,并且不应在测试之外使用,这将是一个非常糟糕的做法,在您的实际项目中使用 Factory 或 Builder .
无论如何,我认为最好的解决办法是重新考虑你类。
示例:
public class People {
public People(String firstName, String lastName, Date birth, Date death) {
}
}
如您所见,控制所有给定参数的格式是否正确且不为空是一件很痛苦的事情。
通过这种方式可以减少传递给方法的参数数量。
public class People {
public People(PeopleNames names, Period period) {
}
}
public class PeopleNames {
public People(String firstName, String lastName) {
}
}
public class PeopleNames {
public People(Date begin, Date end) {
}
}
使用 PowerMockito 的抑制。
import org.powermock.api.support.membermodification.MemberModifier;
import org.powermock.api.support.membermodification.MemberMatcher;
suppress(MemberMatcher.constructor(ExampleClass.class))