我必须在某个类中测试一个方法,如下所示:
public class aClassToTest{
private SomeService someService = new SomeService();
public String methodToTest(){
String data = someService.getData();
//....
}
}
因此,我已经模拟了SomeService类来返回我的模拟对象而不是原始的SomeService对象。我已经通过PowerMockito的每种@Test
方法做到了这一点
SomeService someServiceMock = mock(SomeService.class);
when(someServiceMock.getData().thenReturn(Data myMockedData)
PowerMockito.whenNew(SomeService.class).withAnyArguments().thenReturn(someServiceMock);
我在Test类上方有这个注释:
@PrepareForTest({aClassToTest.class, SomeService.class})
如果只有一个测试,那很好,但是如果有几个测试,someServiceMock.getData()
每次都会从第一个测试返回数据,尽管事实是,我在每个测试中都使用新数据来模拟它。我尝试在每个@PrepareForTest({aClassToTest.class, SomeService.class})
方法的上方添加注释@Test
,但是经过几次测试后,我有了一个OutOfMemoryError
,现在只有在运行所有测试的整个Test类时,它才起作用方法,但是如果我分别运行测试方法,则会出现No tests found for given includes
错误。
我有这样的测试班:
@RunWith(PowerMock.class)
@PrepareForTest({aClassToTest.class, SomeService.class})
public class TestClass{
private void doMockSomeService(String testData){
SomeService someServiceMock = mock(SomeService.class);
when(someServiceMock.getData().thenReturn(testData);
PowerMockito.whenNew(SomeService.class).withAnyArguments().thenReturn(someServiceMock);
}
@Test
public void testCase1(){
String expectedResult = "expectedResult1";
doMockSomeService("123");
ClassToTest classToTest = new ClassToTest();
String result = classToTest.methodToTest();
assertEquals(result, expectedResult);
}
@Test
public void testCase2(){
String expectedResult = "expectedResult2";
doMockSomeService("456");
ClassToTest classToTest = new ClassToTest();
String result = classToTest.methodToTest();
assertEquals(result, expectedResult);
}
}
在这种情况下,someService.getData()的返回值始终为“ 123”。
答案 0 :(得分:0)
我不知道为什么这不起作用:
@RunWith(MockitoJUnitRunner.class)
class MyTest {
@Mock private SomeService service;
@InjectMocks private aClassToTest;
@Before
public void initData() {
when(service.getData()).thenReturn(data);
}
@Test
public void test() {
mockData("expected");
String result = aClassToTest.methodToTest();
verify(service).getData(); // method was called
assertEquals("expected", result);
}
private void mockData(String str) {
when(service.getData()).thenReturn(str);
}
}
答案 1 :(得分:0)
配置初始化时,请使用withNoArguments
。同时从SomeService.class
@PrepareForTest
@RunWith(PowerMockRunner.class)
@PrepareForTest(aClassToTest.class)
public class TestClass {
private void doMockSomeService(String testData){
SomeService someServiceMock = PowerMockito.mock(SomeService.class);
PowerMockito.when(someServiceMock.getData().thenReturn(testData);
PowerMockito.whenNew(SomeService.class).withNoArguments()
.thenReturn(someServiceMock);
}
@Test
public void testCase1() {
//Arrange
String expectedResult = "expectedResult1";
doMockSomeService("123");
ClassToTest classToTest = new ClassToTest();
//Act
String result = classToTest.methodToTest();
//Assert
assertEquals(result, expectedResult);
}
@Test
public void testCase2() {
//Arrange
String expectedResult = "expectedResult2";
doMockSomeService("456");
ClassToTest classToTest = new ClassToTest();
//Act
String result = classToTest.methodToTest();
//Assert
assertEquals(result, expectedResult);
}
}
请注意,您必须为创建SomeService的新实例(而不是SomeService本身)的类做准备。
引用How to mock construction of new objects
与powermock遇到的问题分开,这演示了将代码紧密耦合到依赖项而导致难以单独测试的问题。
更可靠的方法是使用依赖反转来遵循显式依赖原理
public class aClassToTest{
private SomeService someService;
@Inject
public aClassToTest(SomeService someService) {
this.someService = someService;
}
public String methodToTest(){
String data = someService.getData();
//....
}
}
这会将依赖关系的创建反转到目标类的外部,并且还非常清楚地说明了该类执行其特定功能所需的条件。
这也使得对被测目标受试者的隔离单元测试更加容易
@RunWith(MockitoJUnitRunner.class)
public class TestClass {
private someServiceMock doMockSomeService(String testData){
someServiceMock = mock(SomeService.class);
when(someServiceMock.getData().thenReturn(testData);
return someServiceMock;
}
@Test
public void testCase1() {
//Arrange
String expected = "expectedResult1";
ClassToTest classToTest = new ClassToTest(doMockSomeService("123"));
//Act
String actual = classToTest.methodToTest();
//Assert
assertEquals(expected, actual);
}
@Test
public void testCase2() {
//Arrange
String expected = "expectedResult2";
ClassToTest classToTest = new ClassToTest(doMockSomeService("456"));
//Act
String actual = classToTest.methodToTest();
//Assert
assertEquals(expected, actual);
}
}
在我看来,仅因为PowerMock允许我们在其他对象中模拟对象创建的能力,但这并不意味着应该鼓励我们设计难以维护和孤立测试的紧密耦合类。
如果找不到可行的解决方案,此答案也将替代当前方法。
答案 2 :(得分:-1)
谢谢大家。通过更改类的设计解决的问题,应该进行测试。