Sử dụng PowerMockito.whenNew () không bị chế nhạo và phương thức gốc được gọi


99

Tôi có một đoạn mã giống như sau:

Class A {
  public boolean myMethod(someargs) {
    MyQueryClass query = new MyQueryClass();
    Long id = query.getNextId();
    // some more code
  }
}
Class MyQueryClass     {
  ....
  public Long getNextId() {
    //lot of DB code, execute some DB query
    return id;
  }
}

Bây giờ tôi đang viết một bài kiểm tra cho A.myMethod(someargs). Tôi muốn bỏ qua phương thức thực query.getNextId()và thay vào đó trả về giá trị sơ khai. Về cơ bản, tôi muốn chế nhạo MyQueryClass.

Vì vậy, trong trường hợp thử nghiệm của tôi, tôi đã sử dụng:

MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);

boolean b = A.getInstance().myMethod(args);

//asserts

Tôi đã sử dụng @RunWith(PowerMockRunner.class)@PrepareForTest({MyQueryClass.class})trong phần đầu của lớp thử nghiệm của tôi.

Nhưng khi tôi gỡ lỗi kiểm tra, nó vẫn đang gọi phương thức thực getNextId()của MyQueryClasslớp.

Tôi còn thiếu gì ở đây? Bất cứ ai có thể giúp đỡ vì tôi mới sử dụng Mockito và PowerMockito.

Câu trả lời:


219

Bạn cần đặt lớp mà hàm tạo được gọi vào @PrepareForTestchú thích thay vì lớp đang được xây dựng - xem Cấu tạo mô phỏng các đối tượng mới .

Trong trường hợp của bạn:

@PrepareForTest(MyQueryClass.class)

@PrepareForTest(A.class)

Tổng quát hơn:

@PrepareForTest(NewInstanceClass.class)

@PrepareForTest(ClassThatCreatesTheNewInstance.class)


1
Cảm ơn rất nhiều. Nó đã hoạt động ngay sau khi bao gồm lớp hiện tại, chẳng hạn như A trong @PrepareForTest.
user3942446

2
Tôi cũng dành một thời gian cho việc này. Cảm ơn @TrueDub. Bởi vì tài liệu tham khảo đã lỗi thời. Tôi chỉ cập nhật nó. github.com/jayway/powermock/wiki/MockConstructor Nó nói: Sử dụng chú thích @PrepareForTest (ClassThatCreatesTheNewInstance.class) ở cấp lớp của trường hợp thử nghiệm.
Victor Choy

4
Tôi có cùng một vấn đề, nhưng giải pháp này không làm việc cho tôi
dexter

3
Giải pháp này sẽ không hoạt động nếu bạn đang sử dụng eclemma để bảo hiểm mã. Thêm lớp đang kiểm tra vào @PrepareForTest sẽ dẫn đến mức độ phù hợp là 0% cho lớp đó
ACV

2
Giải pháp sẽ hoạt động - kiểm tra thực hiện chính xác. Rõ ràng là eclemma không được trang bị để đối phó với PowerMockito. Phạm vi mã không phải là một phần của câu hỏi này.
TrueDub

3

Như @TrueDub đã đề cập trong câu trả lời được chấp nhận của anh ấy, bạn cần thêm lớp mà hàm tạo được gọi vào @PrepareForTest.

Tuy nhiên, nếu bạn làm điều này, phạm vi bảo hiểm cho lớp đó như được báo cáo bởi eclemma và Sonar sẽ bằng 0 cho lớp đó

Powermockito wiki

Chúng tôi sẽ thay thế Javassist bằng ByteBuddy (# 727) và nó sẽ giúp giải quyết vấn đề cũ này. Nhưng hiện tại KHÔNG CÓ CÁCH ĐỂ SỬ DỤNG PowerMock với thiết bị đo JaCoCo On-the-fly. Và không có giải pháp nào để có được vùng phủ mã trong IDE.

Vì vậy, giải pháp ở đây sẽ là cấu trúc lại mã thực để sử dụng một nhà máy tĩnh sẽ trả về một thể hiện của lớp đó và sau đó mô phỏng nó một cách tĩnh.


Đồng ý với bình luận của bạn.
Lathy

Đó không phải là một vấn đề trong Intellij.
ACV

0

Có lẽ bạn chỉ có thể sử dụng

Mockito.doReturn(value).when(xxx)
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.