PowerMockito giả lập phương thức tĩnh đơn và đối tượng trả về


98

Tôi muốn mô phỏng một phương thức tĩnh m1 từ một lớp có chứa 2 phương thức tĩnh, m1 và m2. Và tôi muốn phương thức m1 trả về một đối tượng.

Tôi đã thử cái sau

1)

PowerMockito.mockStatic(Static.class, new Answer<Long>() {
         @Override
         public Long answer(InvocationOnMock invocation) throws Throwable {
            return 1000l;
         }
      });

Điều này đang gọi cả m1 và m2, có kiểu trả về khác, vì vậy nó tạo ra lỗi không khớp kiểu trả về.

2) PowerMockito.when(Static.m1(param1, param2)).thenReturn(1000l); Nhưng điều này không được gọi khi m1 được thực thi.

3) PowerMockito.mockPartial(Static.class, "m1"); Đưa ra lỗi trình biên dịch khiến mockPartial không khả dụng mà tôi gặp phải từ http://code.google.com/p/powermock/wiki/MockitoUsage .

Câu trả lời:


135

Những gì bạn muốn làm là sự kết hợp của một phần của 1 và tất cả của 2.

Bạn cần sử dụng PowerMockito.mockStatic để kích hoạt tính năng giả lập tĩnh cho tất cả các phương thức tĩnh của một lớp. Điều này có nghĩa là có thể khai thác chúng bằng cú pháp when-thenReturn.

Nhưng quá tải 2 đối số của mockStatic mà bạn đang sử dụng cung cấp một chiến lược mặc định cho những gì Mockito / PowerMock sẽ thực hiện khi bạn gọi một phương thức mà bạn chưa xác định rõ ràng trên ví dụ giả.

Từ javadoc :

Tạo mô hình lớp với một chiến lược cụ thể cho câu trả lời của nó cho các tương tác. Đây là tính năng khá tiên tiến và bạn không cần nó để viết các bài kiểm tra tốt. Tuy nhiên, nó có thể hữu ích khi làm việc với các hệ thống cũ. Đây là câu trả lời mặc định vì vậy nó sẽ chỉ được sử dụng khi bạn không thực hiện lệnh gọi phương thức.

Các mặc định chiến lược stubbing mặc định là chỉ cần vô lại, 0 hay sai cho đối tượng, số lượng và boolean phương pháp có giá trị. Bằng cách sử dụng quá tải 2-arg, bạn đang nói "Không, không, không, theo mặc định, hãy sử dụng phương thức trả lời của lớp con Answer này để nhận giá trị mặc định. Nó trả về giá trị Long, vì vậy nếu bạn có phương thức tĩnh trả về thứ gì đó không tương thích với Dài, có một vấn đề.

Thay vào đó, hãy sử dụng phiên bản 1-arg của mockStatic để cho phép khai thác các phương thức tĩnh, sau đó sử dụng when-thenReturn để chỉ định những việc cần làm cho một phương thức cụ thể. Ví dụ:

import static org.mockito.Mockito.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

class ClassWithStatics {
  public static String getString() {
    return "String";
  }

  public static int getInt() {
    return 1;
  }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStatics.class)
public class StubJustOneStatic {
  @Test
  public void test() {
    PowerMockito.mockStatic(ClassWithStatics.class);

    when(ClassWithStatics.getString()).thenReturn("Hello!");

    System.out.println("String: " + ClassWithStatics.getString());
    System.out.println("Int: " + ClassWithStatics.getInt());
  }
}

Phương thức static có giá trị chuỗi được khai thác để trả về "Hello!", Trong khi phương thức static có giá trị int sử dụng giá trị mặc định, trả về 0.


1
Có cần phải chơi lại không?
Balaji Boggaram Ramanarayan

Hmm ... sorta có vẻ như vậy. Có lẽ PowerMockito thực hiện PowerMock phát lại cho bạn? Tôi cũng thắc mắc về điều đó.
djangofan

3
Nhưng nếu tôi cần chắc chắn rằng một số phương thức tĩnh được gọi với các đối số chính xác thì sao?
elTomato

6
Các @PrepareForTestchú thích nên lớp mà gọi phương pháp tĩnh, không phải là lớp học, nơi các phương pháp tĩnh là.
Hazel Troost

5
@HazelTroost - Không, OP đã đúng. Đây là lớp chứa phương thức tĩnh cần được chuẩn bị để kiểm tra. Vì vậy, @PrepareForTest(ClassWithStatics.class)là đúng.
arry36
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.