Java 为工厂类创建的对象注入模拟
我有以下课程:Java 为工厂类创建的对象注入模拟,java,spring,junit,mockito,Java,Spring,Junit,Mockito,我有以下课程: public class MyClass { private Apple apple; public void myMethod() { apple = AppleFactory.createInstance(someStringVariable); .... .... .... } } 和测试类: @RunWith(MockitoJUnitRunner.class) public
public class MyClass {
private Apple apple;
public void myMethod() {
apple = AppleFactory.createInstance(someStringVariable);
....
....
....
}
}
和测试类:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@InjectMocks
MyClass myClass;
@Test
public void myMethod(){
...
...
...
}
}
如何在MyClass中将Apple实例作为模拟注入?您有3种可能解决此问题: 抽象工厂:不要使用静态方法,而是使用具体的工厂类:
public abstract class AppleFactory {
public Apple createInstance(final String str);
}
public class AppleFactoryImpl implements AppleFactory {
public Apple createInstance(final String str) { // Implementation }
}
在测试类中,模拟工厂:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
private AppleFactory appleFactoryMock;
@Mock
private Apple appleMock;
@InjectMocks
MyClass myClass;
@Before
public void setup() {
when(appleFactoryMock.createInstance(Matchers.anyString()).thenReturn(appleMock);
}
@Test
public void myMethod(){
...
...
...
}
}
PowerMock:使用PowerMock创建静态方法的模拟。看看是怎么做的
可测试类:将苹果
创建包装在一个受保护的
方法中,并创建一个覆盖它的测试类:
public class MyClass {
private Apple apple;
public void myMethod() {
apple = createApple();
....
....
....
}
protected Apple createApple() {
return AppleFactory.createInstance(someStringVariable);
}
}
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
private Apple appleMock;
@InjectMocks
MyClass myClass;
@Test
public void myMethod(){
...
...
...
}
private class TestableMyClass extends MyClass {
@Override
public void createApple() {
return appleMock;
}
}
}
当然,在测试类中,您应该测试TestableMyClass
,而不是MyClass
我会告诉你我对每种方法的看法:
PowerMock
选项是我最不喜欢的选项——你没有追求更好的设计,而是忽略并隐藏你的问题。但这仍然是一个有效的选择除Avi提出的解决方案外,您还可以选择第四种可能性: 注入工厂: 对我来说,这是当您已经有代码要重构时的最佳选择。使用此解决方案,您不必更改生产代码,只需更改工厂类和测试
public class AppleFactory
{
private static Apple _injectedApple;
public static createInstance(String str)
{
if (_injectedApple != null)
{
var currentApple = _injectedApple;
_injectedApple = null;
return currentApple;
}
//standard implementation
}
public static setInjectedApple(Apple apple)
{
_injectedApple = apple;
}
}
现在,您可以简单地使用静态工厂:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
private Apple appleMock;
@InjectMocks
MyClass myClass;
@Before
public void setup() {
AppleFactory.setInjectedApple(appleMock);
}
@Test
public void myMethod(){
...
...
...
}
}
关于Avi和Ev0oD的第一个答案。抽象类只能扩展,不能实现
public abstract class AppleFactory {
public abstract Apple createInstance(final String str);
}
public class AppleFactoryImpl extends AppleFactory {
public Apple createInstance(final String str) { // Implementation }
}
太棒了,谢谢。我必须在我的情况下使用Mockito,所以我将使用抽象工厂或可测试类选项。@saravana_pc-我将我的排名添加到问题中。不过,您可以将
mockito
与powermock一起使用。在实现抽象工厂模式时,不必使用@Mock
和@InjectMock
而是可以使用它们的等效方法(这样就可以去掉@RunWith(MockitoJUnitRunner.class)
声明),接口不是更合适吗?我不理解抽象类的必要性,它不是只与实现一起工作吗?此外,虽然我喜欢这个想法,但它在某种程度上没有实现工厂的目标(您需要创建工厂的实例)。现在mockito可以模拟静态方法,但我不能使用更新的版本:,那么如何测试AppleFactory呢?