为Factory类创建的对象注入模型



我有以下类:

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实例作为mock?

您有三种解决方案:

抽象工厂:不要使用静态方法,而是使用具体的工厂类:

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创建静态方法的mock。看看我对一个相关问题的回答,看看它是如何完成的。

可测试类:将Apple创建封装在protected方法中,并创建一个覆盖它的测试类:

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

我会告诉你我对每种方法的看法:

  1. 抽象工厂方法是最好的方法-这是一个隐藏实现细节的清晰设计

  2. 可测试类-是第二个选项,需要最少的更改

  3. 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(){
...
...
...
}
}

相关内容

  • 没有找到相关文章

最新更新