繁体   English   中英

Mockito - mocking 旧版 class 构造函数

[英]Mockito - mocking legacy class constructor

我正在为 class 编写 JUnit,它通过构造函数引用旧版 class。 旧版 class 位于第三方 jar 中,因此我无法对其进行重构以使生活更轻松......

这是正在测试的 class...

public MyClass {

    public String methodToTest(String param) {
        LegacyClass legacy = new LegacyClass(param);
        *..... etc ........*
    }
}

这就是我在 mockito JUnit 中尝试做的事情。

public MyClassTest {

    @Test
    public void testMethodToTest() throws Exception {
        LegacyClass legacyMock = mock(LegacyClass.class);
        when(*the LegacyClass constructor with param is called*).thenReturn(legacyMock);
        *.... etc.....*
    }
}

关于我如何做到这一点的任何想法????

LegacyClass一个构建器

public class LegacyClassBuilder {

    public LegacyClass build(String param) {
        return new LegacyClass(param);
    }

}

这样您的 class 就可以进行测试,因此它可以创建具有正确参数的LegacyClass

public MyClass {

    private LegacyClassBuilder builder;

    public setBuilder(LegacyClassBuilder builder) {
        this.builder = builder;
    }

    public String methodToTest(String param) {
        LegacyClass legacy = this.builder.build(param);
        ... etc
    }
}

测试将如下所示:

// ARRANGE
LegacyClassBuilder mockBuilder = mock(LegacyClassBuilder.class);
LegacyClass mockLegacy = mock(LegacyClass.class); 
when(mockBuilder.build(anyString()).thenReturn(mockLegacy);

MyClass sut = new MyClass();
sut.setBuilder(mockBuilder);
String expectedParam = "LOLCAT";


// ACT
sut.methodToTest(expectedParam);

// ASSERT
verify(mockBuilder).build(expectedParam);

如果LegacyClass恰好是final的,那么您需要为MyClass将使用的LegacyClass创建非最终包装器。

您可以使用 PowerMockito 框架:

import static org.powermock.api.mockito.PowerMockito.*;

whenNew(LegacyClass.class)
  .withParameterTypes(String.class)
  .withArguments(Matchers.any(String.class))
  .thenReturn(new MockedLegacyClass(param));

然后根据您的测试需要编写您的 MockedLegacyClass 实现。

我相信不可能使用 Mockito 来模拟构造函数。 相反,我会建议以下方法:

  public MyClass {

    public String methodToTest(String param) {
     if(legacy== null){
      //when junit runs, you will get mocked object (not null), hence don't initialize 
        LegacyClass legacy = new LegacyClass(param);
      }
        *..... etc ........*
    }
}

public MyClassTest {

@InjectMock
Myclass myclass; // inject mock the real testable class
@Mock
LegacyClass legacy

@Test
public void testMethodToTest() throws Exception {    
    // when(legacy-constructor).thenReturn() ---not Required
    // instead directly mock the required methods using mocked legacy object
    when(legacy.getSomething(Mockito.any(String.class))).thenReturn(null);
        *.... etc.....*
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM