为Factory类创建的对象注入Mocks

sar*_*_pc 15 java junit spring mockito

我有以下课程:

public class MyClass {        
    private Apple apple;

    public void myMethod() {
       apple = AppleFactory.createInstance(someStringVariable);
       ....
       ....
       ....
    }
}
Run Code Online (Sandbox Code Playgroud)

和测试类:

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

        @InjectMocks 
        MyClass myClass;

        @Test
        public void myMethod(){
         ...
         ...
         ...
        }
    }
Run Code Online (Sandbox Code Playgroud)

我如何在MyClass中注入Apple实例作为模拟?

Avi*_*Avi 22

您有3种可能性来解决这个问题:

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

public abstract class AppleFactory {
    public Apple createInstance(final String str);
}

public class AppleFactoryImpl implements AppleFactory {
    public Apple createInstance(final String str) { // Implementation }
}
Run Code Online (Sandbox Code Playgroud)

在您的测试类中,模拟工厂:

@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(){
     ...
     ...
     ...
    }
}
Run Code Online (Sandbox Code Playgroud)

PowerMock:使用PowerMock创建静态方法的模拟.看看我对相关问题的回答,看看它是如何完成的.

可测试类:使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;
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,在你的测试课中你应该测试TestableMyClass而不是MyClass.

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

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

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

  3. PowerMock选项是我最不喜欢的 - 您可以忽略并隐藏您的问题,而不是寻求更好的设计.但这仍然是一个有效的选择.

  • 在实现抽象工厂模式时,接口不是更合适吗? (3认同)