自己写单元测试时的总结:
- 静态方法:
在类上添加 @RunWith(PowerMockRunner.class) @PrepareForTest({StaticTest.class}) 方法: PowerMockito.mockStatic(StaticTest.class); PowerMockito.when(StaticTest.static1()).thenReturn("static"); // 方法的参数尽量一致 PowerMockito.doNothing().when(StaticTest.class, "static1", file, null); String result = StaticTest.static1();
如果mockStatic的类存在static代码块, 则mock的时候会先执行static代码块中的内容, 然后再mock, 所以需要将static里面的内容也mock
- mockito的基本格式
@InjectMocks @Spy private AccountInfoController fixture = new AccountInfoController(); @Mock private AccountInfoService accountInfoService; @Mock private HttpServletRequest request; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } doReturn(map).when(accountInfoService).addAccountInfo("a", "user", 0, 1, "xxx", "opera", 1, 1);
- new:
File file = new File(path); return file.exists(); 模拟: @RunWith(PowerMockRunner.class) @PrepareForTest(必须是待测试方法所在的类.class) File file = PowerMockito.mock(File.class); PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file); PowerMockito.whenNew(File.class).withArguments(Mockito.anyString()).thenReturn(file); PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(file); PowerMockito.when(file.exists()).thenReturn(true); 注: 待测试方法的意思是: 比如测试A类中的methodB()方法,则prepareForTest里包含A.class, 而不是A的测试类
- void:
PowerMockito.doNothing().when(casService).addSupplier(anyLong(), any(ServiceKey.class));
- 抽象类:
BaseTransaction baseTransaction = Mockito.mock(BaseTransaction.class, Mockito.CALLS_REAL_METHODS);
- @Mock与MockitoAnnotations.initMocks(this);
- 总结
8. Progress process = Mockito.mock(Progress.class); mock只是mock一个类/接口的对象, mock出来的对象并不会自动替换掉正式代码里面的对象,你必须要有某种方式把mock对象应用到正式代码里面 9. PasswordValidator spyValidator = Mockito.spy(PasswordValidator.class); Mockito.when(spyValidator.verifyPassword(anyString())).thenReturn(true); 10. spy与mock的唯一区别就是默认行为不一样:spy对象的方法默认调用真实的逻辑,mock对象的方法默认什么都不做,或直接返回默认值
- 总结
如果mock的方法在多线程中, 则要在test方法中进行休眠处理,防止主线程结束导致多线程没有正常结束
- 抛出异常:
PowerMockito.doThrow(new MySelfException("111")).when(object).method(Mockito.anyString(),Mockito.anyInt());
- 总结
spy的对象也可以进行mock。mock的方法参数类型必须与实际参数一致,尤其注意null参数 Mockito.doNothing().when(fixture).addAccountInfo(Mockito.anyString(), Mockito.eq(null));
- spy对象的私有属性: 反射获取
Field field = spy类.class.getDeclaredField("a"); field.setAccessible(true); //粗爆的改成可访问,不管现有修饰 field.set(spy对象, 3);
- powermockito spy方法 内部调用私有方法
@PrepareForTest({A.class}) PowerMockito.doNothing().when(fixture, "method", Mockito.anyInt(), Mockito.anyString()); PowerMockito.doreturn(*).when(fixture, "method1", Mockito.anyInt(), Mockito.anyString());
- mock私有方法: 用反射
private Method privateMethod; @Before public void setUp() throws Exception { privateMethod = A.class.getDeclaredMethod("privateMethod", Integer.class, String.class); privateMethod.setAccessible(true); } try { privateMethod.invoke(fixture, 1, "1"); }catch (Exception e) { if (e instanceof InvocationTargetException) { InvocationTargetException e1 = (InvocationTargetException) e; System.out.println(e1.getCause().getMessage()); } else { System.out.println(e.getMessage()); } }
- 同时mock一个方法多次, 可以分开调用;如果超过设定次数,则方法取值为最后一个的值
PowerMockito.when(A.method1).thenReturn(result1).thenReturn(result2).thenReturn(result3);
- 数组
Mockito.any(String[].class)
- HttpClient模拟
private HttpClient mockHttpClient; private HttpPost mockHttpPost; private HttpResponse mockHttpResponse; private HttpEntity mockHttpEntity; private InputStream mockInputStream; private InputStreamReader mockInputStreamReader; private BufferedReader mockBufferedReader; ProtocolVersion protocolVersion = new ProtocolVersion("1", 2,1); StatusLine statusLine = new BasicStatusLine(protocolVersion, 200, ""); PowerMockito.mockStatic(HttpClientBuilder.class); PowerMockito.when(HttpClientBuilder.create()).thenReturn(mockHttpClientBuilder); PowerMockito.doReturn(mockHttpClient).when(mockHttpClientBuilder).build(); PowerMockito.doReturn(mockHttpResponse).when(mockHttpClient).execute(Mockito.any(HttpPost.class)); PowerMockito.doReturn(statusLine).when(mockHttpResponse).getStatusLine();
- 正常情况(when().then()的比对)
PowerMockito.doThrow(new Exception("111")).when(a).method(); a. PowerMockito.doReturn(null).when(a).method(); b. PowerMockito.when(a.method()).thenReturn(null); c. PowerMockito.doThrow(exception).when(mock).someVoidMethod(); d. PowerMockito.doReturn(null).when(a.method()); 区别: 1. 首先mock对象需要花费时间。 2. 如果mock对象过程结束了,则三个方法可以随便调用,即在setup的方法(@Before)中先初始化mock对象,那么三个方法可以随意调用 3. 如果是在方法内部才开始mock对象,即(Power)Mockito.mock(A.class),那么最好是使用b或c的方法,能保证在mock对象结束后再返回结果,否则会提示UnfinishedStubbingException异常 4. 建议用b方法 5. a和d的区别是,如果a是spy的对象,需要用a
- kafka模拟: 使用kafka自带的MockProducer
MockProducer mockProducer = PowerMockito.mock(MockProducer.class); Field producer = AlertUtil.class.getDeclaredField("producer"); producer.setAccessible(true); producer.set(AlertUtil.class, mockProducer); PowerMockito.when(mockProducer.send(Mockito.any(ProducerRecord.class))).thenReturn(null);
- 当涉及文件操作时
a. 需要先创建,然后读取* File file = new File(this.getClass().getResource("").getFile() + "fileName"); if (!file.exists()) { generateFile(file); } else { file.delete(); generateFile(file); } FileInputStream fileInputStream = new FileInputStream(file); PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(fileInputStream); public void generateFile(File file) { Document document = DocumentHelper.createDocument(); Element rootElement = document.addElement("allocations"); Element rootQueueElement = rootElement.addElement("queue"); rootQueueElement.addAttribute("name", "root"); Element aclSubmitApps = rootQueueElement.addElement("aclSubmitApps"); aclSubmitApps.addText(" "); Element aclAdministerApps = rootQueueElement.addElement("aclAdministerApps"); aclAdministerApps.addText(" "); Element queueChild = rootQueueElement.addElement("queue"); queueChild.addAttribute("name", "999"); queueChild.addElement("minResources").setText("1 mb,1 vcores"); queueChild.addElement("maxResources").setText("1 mb,1 vcores"); queueChild.addElement("maxRunningApps").setText("1"); queueChild.addElement("maxAMShare").setText("1"); queueChild.addElement("aclSubmitApps").setText("1"); queueChild.addElement("weight").setText("1"); queueChild.addElement("schedulingPolicy").setText("1"); XMLWriter writer = null; try { // 把内存中的dom树 写回到一个xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); // 指定XML编码 输出到output.xml format.setEncoding("UTF-8"); format.setTrimText(false); writer = new XMLWriter(new FileOutputStream(file), format); writer.write(document); writer.flush(); } catch (Exception e) { } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { } } } } b. 直接将文件写在内存中: 太费事,不好实现,暂时没想到好方法
- 总结
a.只要是接口调用,都可以直接mock: PowerMockito.mock(A.class); b.在一个测试方法中,mock方法是全方法有效,除非是改变方法的方法值,否则不需要再次调用;同理mock的对象也是在方法内一直有效。 c.若mock对象的方法没有设定返回值,那么返回的结果是默认值:单个对象返回的是null,集合返回的是大小为0的集合 d.mock静态类的时候,mockStatic()括号中的类一定要是static方法所在的类,否则可能出现问题(即使继承也不行);非static类可以
- mock数据库连接:
Connection connection = PowerMockito.mock(Connection.class); Statement statement = PowerMockito.mock(Statement.class); ResultSet resultSet = PowerMockito.mock(ResultSet.class); PowerMockito.mockStatic(DBConnectUtil.class); PowerMockito.when(DBConnectUtil.getConnection(null, null, null, null)).thenReturn(connection); PowerMockito.when(connection.createStatement()).thenReturn(statement); PowerMockito.when(statement.executeQuery(Mockito.anyString())).thenReturn(resultSet); PowerMockito.when(resultSet.ne()).thenReturn(true).thenReturn(false); PowerMockito.when(resultSet.getString(Mockito.anyInt())).thenReturn("1").thenReturn("2");
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228387.html原文链接:https://javaforall.net
