PowerMockito整理

@PrepareForTest的使用场景

  • 当使用PowerMockito.whenNew方法时,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。
  • 当需要mock final方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是final方法所在的类。
  • 当需要mock静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是静态方法所在的类。
  • 当需要mock私有方法的时候, 只是需要加注解@PrepareForTest,注解里写的类是私有方法所在的类
  • 当需要mock系统类的静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解里写的类是需要调用系统方法所在的类

示例:

@PrepareForTest({类名.class, 类名.class})

@PowerMockIgnore

忽略一些编译报错使用
优快云-参考链接

示例:

@PowerMockIgnore({"javax.management.*", "包路径"})

mock一个对象

注意:@Mock注解的变量如果通过new得到的仍旧是一个真实对象,只有通过PowerMockito.mock(被mock的类的类名.class)得到的才是mock对象。

被mock的类的类名 mock对象 = PowerMockito.mock(被mock的类的类名.class);
PowerMockito.whenNew(被mock的类的类名).withArguments(参数列表).thenReturn(mock对象);

mock静态方法

PowerMockito.mock(含有静态方法的类名.class);
PowerMockito.when(含有静态方法的类名.要mock的静态方法).thenReturn(...);

mock私有属性

被mock的类的类名 对应含有该私有属性的类的mock对象 = PowerMockito.mock(被mock的类的类名.class);
MemberModifier.field(含有该私有属性的类的类名.class, "要mock的私有属性的变量名").set(对应含有该私有属性的类的mock对象,用于替换私有属性的新的值);
<think>好的,我现在需要解决用户的问题:“如何使用PowerMock来测试或验证方法是否抛出了预期的异常,请求PowerMockito verify throws exception示例”。首先,我要回想一下PowerMockMockito的相关知识,尤其是处理异常测试的部分。 用户提到的是PowerMock,通常与Mockito结合使用,即PowerMockito。PowerMock主要用于解决Mockito的局限性,比如静态方法、构造函数、final类等的模拟。但这里用户关心的是异常验证,可能涉及到这些特殊情况。 首先,我需要确定验证异常的一般方法。在JUnit中,可以使用@Test(expected=Exception.class)或者使用ExpectedException规则,或者使用try-catch块。但在使用Mockito或PowerMockito时,可能需要模拟方法抛出异常,然后验证是否抛出了该异常。 用户的问题可能分为两部分:如何让模拟的方法抛出异常,以及如何验证被测方法是否抛出了预期的异常。或者,可能需要验证某个方法是否被调用并抛出了异常。需要明确用户的具体需求。 假设用户有一个类,其中的某个方法在被调用时会抛出异常,用户想要在单元测试中模拟这种情况,并验证当调用该方法时,确实抛出了预期的异常。或者,用户可能在测试某个方法时,希望模拟依赖对象的方法抛出异常,然后验证被测方法是否正确处理了这个异常,比如是否捕获并重新抛出,或者是否触发了特定的逻辑。 根据Mockito的标准做法,可以使用when().thenThrow()来模拟方法抛出异常。例如: Mockito.when(mockObject.someMethod()).thenThrow(new RuntimeException()); 然后,在测试中调用该方法,并期望捕获到该异常。但用户可能遇到的问题是,当被测试的方法涉及到静态方法、构造函数、私有方法等,这时候就需要PowerMockito来增强模拟能力。 例如,如果需要模拟一个静态方法抛出异常,就需要使用PowerMockito.mockStatic(),然后设置when().thenThrow()。例如: PowerMockito.mockStatic(MyClass.class); PowerMockito.when(MyClass.staticMethod()).thenThrow(new IOException()); 然后,当被测代码调用这个静态方法时,就会抛出异常,从而可以验证后续的行为。 但用户的问题可能更偏向于如何验证某个方法是否抛出了异常,而不仅仅是模拟。或者,可能在调用某个方法后,使用verify来确认该方法被调用,并且抛出了异常。这里可能需要澄清:通常,验证异常是否被抛出是通过测试的expected参数或者捕获异常来实现的,而verify用于验证方法的调用次数、参数等。 例如,如果有一个对象被模拟,当调用它的某个方法时,期望它抛出异常,然后在测试中调用被测方法,该方法应该触发这个模拟方法,从而抛出异常。此时,测试应该捕获该异常,并断言异常类型。或者,如果被测方法本身应该抛出异常,那么测试应该使用expected参数。 但用户的问题可能更具体地涉及PowerMockito的verify方法结合异常验证。可能用户想要验证某个方法在调用时抛出了异常,或者是否被调用,并且在调用时抛出了异常。这个时候,可能需要结合Mockito的verify来检查方法是否被调用,同时处理异常的抛出。 举个例子,假设有一个类ClassUnderTest,它有一个依赖的实例Dependency,其中Dependency有一个方法doSomething(),当调用时可能抛出异常。在测试中,我们模拟Dependency,设置当doSomething()被调用时抛出异常,然后调用ClassUnderTest的方法,并验证是否处理了该异常,或者是否抛出了预期的异常。 步骤可能如下: 1. 使用PowerMockito.mock()创建Dependency的模拟对象。 2. 使用PowerMockito.when().thenThrow()来设置当doSomething()被调用时抛出异常。 3. 调用被测试的方法,传入模拟对象。 4. 使用JUnit的expected异常验证,或者使用try-catch块来捕获异常并断言。 这里可能不需要特别的verify步骤来验证异常是否被抛出,而是通过测试是否抛出异常来验证。不过,如果用户想要验证模拟对象的某个方法被调用并且抛出了异常,这可能不太适用,因为模拟对象的方法已经被设置为抛出异常,当被调用时会自动抛出。此时,更关注的是被测方法是否正确处理了这个异常。 不过,用户的问题可能更偏向于如何设置模拟对象抛出异常,并在测试中验证该异常是否被抛出。因此,可能需要给出一个具体的示例。 例如,测试一个Service类中的方法,当调用DAO层的某个方法时抛出SQLException,期望Service方法将异常包装并抛出特定的业务异常。 示例代码: @Test(expected = BusinessException.class) public void testMethodWhenDaoThrowsException() throws Exception { Dao dao = PowerMockito.mock(Dao.class); PowerMockito.when(dao.getData()).thenThrow(new SQLException()); Service service = new Service(dao); service.processData(); // 应该调用dao.getData()并抛出SQLException,然后转换成BusinessException } 但这里,Service可能将SQLException捕获并抛出BusinessException,因此测试的expected应为BusinessException。 然而,如果用户的问题是如何验证某个方法被调用并且抛出了异常,可能需要结合Mockito的verify来确认方法被调用了,同时处理异常的抛出。 另外,在PowerMockito中,如果需要验证静态方法是否被调用,可能需要使用PowerMockito.verifyStatic()等。 可能需要给出一个具体的例子,比如: // 测试某个实例方法调用静态方法,而静态方法被模拟抛出异常 @RunWith(PowerMockRunner.class) @PrepareForTest({UtilityClass.class}) public class TestClass { @Test(expected = CustomException.class) public void testMethod() throws Exception { PowerMockito.mockStatic(UtilityClass.class); PowerMockito.when(UtilityClass.staticMethod()).thenThrow(new IOException()); ClassUnderTest underTest = new ClassUnderTest(); underTest.doSomething(); // 内部调用UtilityClass.staticMethod(),应该抛出IOException,但可能被包装成CustomException } } 或者,如果被测方法直接抛出模拟的异常,则expected应该匹配该异常类型。 另外,用户可能想要验证某个方法是否抛出了异常,而不仅仅是模拟它抛出异常。例如,被测方法在正常情况下不会抛出异常,但在某些条件下会抛出异常,此时需要触发这些条件,并验证异常是否被正确抛出。这时候可能需要使用PowerMock来修改类的行为,以触发这些条件。 例如,被测方法内部调用了一个私有方法,该私有方法在某种情况下会抛出异常。使用PowerMock的when方法可能无法直接模拟私有方法,但可以通过spy部分模拟对象,并结合when来设置私有方法抛出异常。 示例: @RunWith(PowerMockRunner.class) @PrepareForTest(ClassUnderTest.class) public class TestClass { @Test(expected = SomeException.class) public void testPrivateMethodThrowsException() throws Exception { ClassUnderTest spy = PowerMockito.spy(new ClassUnderTest()); PowerMockito.doThrow(new SomeException()).when(spy, "privateMethodName"); spy.publicMethod(); // 调用publicMethod,内部调用privateMethodName,此时应该抛出SomeException } } 在这种情况下,使用PowerMockito的doThrow().when()语法来模拟私有方法抛出异常,然后验证当调用publicMethod时是否抛出该异常。 总结,用户可能需要一个示例,展示如何用PowerMockito模拟某个方法(可能是静态、私有、final等)抛出异常,然后在测试中验证是否抛出了预期的异常。因此,回答需要包括以下步骤: 1. 设置测试运行器为PowerMockRunner。 2. 准备需要模拟的类(使用@PrepareForTest)。 3. 模拟静态方法或使用spy来部分模拟对象。 4. 使用PowerMockito.when()或doThrow().when()来设置方法抛出异常。 5. 调用被测方法,并使用@Test(expected)或断言捕获的异常类型。 同时,引用相关的引用内容,比如引用[2]提到PowerMockito弥补了Mockito的不足,可以处理final、private、static方法,因此在处理这些情况时需要用到PowerMockito。 现在,我需要将这些思考整理成一个结构清晰的回答,包含具体的代码示例,并生成相关问题。</think>### 使用PowerMockito验证方法抛出异常的示例 #### 1. 验证普通实例方法抛出异常 若需测试某个对象的方法调用是否抛出异常,可使用 `PowerMockito.when().thenThrow()` 模拟异常,并结合 `@Test(expected)` 验证: ```java @Test(expected = RuntimeException.class) public void testMethodThrowsException() { // 创建模拟对象 MyService mockService = PowerMockito.mock(MyService.class); // 设置模拟方法抛出异常 PowerMockito.when(mockService.doSomething()).thenThrow(new RuntimeException()); // 调用被测方法(触发异常) new ClassUnderTest(mockService).execute(); } ``` 此例中,当 `mockService.doSomething()` 被调用时,会强制抛出 `RuntimeException`,从而验证 `ClassUnderTest.execute()` 是否按预期处理异常[^2]。 --- #### 2. 验证静态方法抛出异常 通过 `PowerMockito.mockStatic()` 模拟静态方法并抛出异常: ```java @RunWith(PowerMockRunner.class) @PrepareForTest({Utility.class}) // 声明需增强模拟的类 public class StaticMethodTest { @Test(expected = IOException.class) public void testStaticMethodThrowsException() { // 模拟静态类 PowerMockito.mockStatic(Utility.class); // 设置静态方法抛出异常 PowerMockito.when(Utility.readFile()).thenThrow(new IOException()); // 调用被测方法(触发静态方法) new FileProcessor().parseFile(); // 内部调用Utility.readFile() } } ``` 此处 `Utility.readFile()` 被模拟抛出 `IOException`,验证 `FileProcessor.parseFile()` 是否抛出该异常。 --- #### 3. 验证私有方法抛出异常 使用 `PowerMockito.spy()` 部分模拟对象,并强制私有方法抛出异常: ```java @RunWith(PowerMockRunner.class) @PrepareForTest({TargetClass.class}) public class PrivateMethodTest { @Test(expected = IllegalArgumentException.class) public void testPrivateMethodThrowsException() throws Exception { TargetClass spy = PowerMockito.spy(new TargetClass()); // 强制私有方法抛出异常 PowerMockito.doThrow(new IllegalArgumentException()) .when(spy, "privateValidate", anyString()); // 调用公有方法(内部调用私有方法) spy.processData("invalid-input"); } } ``` 通过反射机制指定私有方法名称 `privateValidate`,并在调用时触发异常。 --- #### 4. 结合try-catch精确断言异常 若需验证异常消息或状态码,可使用 `try-catch` 捕获异常后断言: ```java @Test public void testExceptionDetails() { try { MyService service = PowerMockito.mock(MyService.class); PowerMockito.when(service.calculate()).thenThrow(new ArithmeticException("Division by zero")); new Calculator(service).run(); fail("Expected ArithmeticException"); } catch (ArithmeticException e) { assertEquals("Division by zero", e.getMessage()); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值