我正在尝试对扩展抽象基类
的类进行单元测试。以下是“类似的类”,以供说明:
public abstract class MyAbstractBaseClass {
@Autowired
private WaterFilter waterFilter;
protected List<String> filterComponents(List<String> allComponents) {
return waterFilter.filter(allComponents);
}
}
public class MyDerivedClass extends MyAbstractBaseClass {
public List<String> filterWater(List<String> allWaterComponents) {
List<String> filteredComponents = this.filterComponents(allWaterComponents); //calls abstract class's filterComponets()
filteredComponents.add("something-else");
return filteredComponents;
}
}
下面是我正在尝试的单元测试:
@RunWith(EasyMockRunner.class)
public class MyDerivedClassTest {
@TestSubject
private MyDerivedClassTest SUT;
@Before
public void setup() {
SUT = new MyDerivedClassTest();
}
@Test
public void test filterWater_HappyCase() {
//I want to mock my abstract class's filterComponents() method
//I am trying this:
EasyMock.expect(SUT.filterComponents(getDummyComponents())).andReturn(getSomeComponents());
//What to replay here?
//EasyMock.replay(...)
List<String> actualResult = SUT.filterWater(getDummyComponents());
//assert something
//What to verify?
//EasyMock.verify(...)
}
}
当我做这个测试的时候
java.lang.NullPointerException
在MyAbstractBaseClass.filter(所有组件)
中
我知道自动连线的“滤水器”没有初始化。但接下来,我只想在我的单元测试中模拟抽象类
的“非抽象”方法。
我该如何使用EasyMock来实现这一点呢?另外,我不知道replay()
和verify()
应该做什么。
当您编写单元测试时,您测试一个对象(通常是它的一个方法),您可以模拟一个对象(通常是它的一个方法)。
但是,您不应该对同一个对象进行单元测试和模拟,因为在某种程度上,这似乎不是很自然:如果您测试一个类的一个方法,那么被测试类的行为应该尽可能保持自然,而不是伪造它自己的方法。
否则,我们可以怀疑单元测试的质量是否良好。
为什么?因为它并不反映我们在运行时会有的类的真实行为,而只是它的行为的一部分。在单元测试中,隔离是研究的,但其背后的想法是将您的被测试类仅与其他类隔离,而不是将其自身的行为隔离。
当然,您可以尝试在受测试类的抽象类中模拟非抽象方法,但测试的设计和质量可能会变得不那么好。
在您的例子中,我想象了两个原因来模拟抽象类中的no-abstract方法:
WaterFilter
字段依赖项使您烦恼,因为它没有被值,因此在测试期间引发异常(NullPointerException)。1)如果您的问题是waterfilter
字段依赖关系。
您应该模拟waterfilter
字段。要模拟一个字段,它必须是可访问和可修改的。在您的情况下,它不是直接的,因为该字段是私有的。
因此,您有两种方法可以访问它来模拟它:
MyDerivedClass
的构造函数中设置字段。您不需要使用EasyMock执行验证操作。只需模拟waterfilter.filter(allComponents)
返回的结果,例如:
waterFilterMock.filter(mockedComponents)
这样,模拟返回您选择的值,并且在您的JUnit断言中,您能够为您的测试中的方法执行正确的断言。
只是为了提供信息,您可以使用Mockito而不是easymock。它更灵活,提供更多可读操作。例如,您可以使用Mockito来实现:
Mockito.when(waterFilterMock.filter()).thenReturn(mockedComponents);
如你所见,它的可读性更强。
2)如果您的问题是您真的想要模拟抽象类中的无抽象方法,因为您已经对它进行了统一测试
您应该修改您的设计,使用组合而不是继承。您将不再使用MyAbstractBaseClass
,而只是两个类之间的依赖关系(其中一个具有另一个的字段)。这样,您就可以以自然的方式模拟filtercomponents()
方法。
这似乎是一个基本问题。但在采访前需要澄清。 我在抽象类中有一个非抽象方法。它的具体类重写了该方法。但我想调用父类的原始方法来调用,而不是重写方法。有什么办法吗? 据我所知,没有办法调用原始方法?
下面是抽象类的代码: 现在,我应该如何为编写单元测试,并且应该如何在中模拟会话? 我在Stackoverflow上尝试了不同的解决方案,但仍然无法模拟它并获得会话模拟。
大家好,我有这个主课堂 错误:(42,8)错误:Home不是抽象的,并且不会覆盖OnFragmentInteractionListener中的onFragmentInteract(String)抽象方法 我创建了一个导航抽屉,并希望有一个新的片段来显示另一个家庭活动的内容。 Android Studio告诉我做个家。类抽象或实现抽象方法。 里面: 我那样做了,但是什么也没有改变。我不能让home类
我有一个子类,它声明了我的抽象超类中的所有方法,但它仍然给我一个错误,说明我的类不是抽象的。我不知道为什么会抛出这个错误。 我得到的具体错误是 PhoneBookEntry.java: 1:错误:PhoneBookEntry不是抽象的,并且不会覆盖可比中的抽象方法compareTo(Object) 我的问题代码: 还有我的子类:
问题内容: Java 8接口默认方法与抽象类中的非抽象方法-两者之间是否有任何区别(除了iface-类,可见性等不同) 默认方法不是Java的后退一步,是否违反Java多年来宣传的本质? 问题答案: 如果抽象子类的具体子类被super()覆盖,则抽象类中的非抽象方法将被调用。因此,存在多种可能性。如果不重写method,则将执行超类方法。如果我们在具体的子类方法中使用super(),则将执行被超类
Java 8接口默认方法与抽象类中的非抽象方法--两者之间有什么区别吗(除了iface-class、可见性等的区别之外) 默认方法是不是在Java中倒退了一步,意味着它违背了Java多年来宣传的本质?!