簡體   English   中英

使用構造函數注入模擬 spring 類

[英]Mocking a spring class with constructor injection

我有以下課程:

@Service
public class SomeClass extends BaseClass {
  private final SomeService someService;

  public SomeClass(SomeService someService) {
    this.someService = someService;
  }

  public List<String> methodToTest(SomeDataClass data) {
    if (!checkData(data)) { // checkData is defined in BaseClass and does lots of unimportant stuff
      throw BadDataException();
    }

    return someService.getData();
  }
}

我現在想使用 Mockito 為 SomeClass 創建測試用例。

  1. 測試是否調用了 checkData()。
  2. 測試 someService.getData() 是否被調用。

使用 Mockito,我管理了測試用例 1:

@Test(expected = BadDataException.class)
public void methodToTest_checkDataCalled() {
  SomeClass mock = mock(SomeClass.class);
  when(mock.methodToTest(any()).thenCallRealMethod();
  when(mock.checkData(any()).thenReturn(false);

  mock.methodToTest(new SomeData());
  verify(mock).checkData(any());
}

但是,我在創建測試用例 #2 時遇到了問題。 我可以使用SomeClass someClass = new SomeClass(mockSomeService)手動創建 SomeClass ,但隨后我需要為廣泛的 checkData() 請求創建模擬數據,我實際上並不想在這個測試用例中進行測試,因為它已經被一個不同的測試,這需要很多不必要的模擬,或者我可以像測試用例 #1 那樣模擬 SomeClass,但是無論我嘗試什么, someService 始終為空。

我嘗試過@InjectMocks、@Mock 等的變體,但我未能創建一個可行的解決方案。

我嘗試過的事情:

@Mock
private SomeService someService;

@Before
public void setUp() {
  someService = mock(SomeService.class);
  when(someService.getData()).thenReturn(Collections.singletonList("Mock"));
}

@Test
public void methodToTest_someServiceCalled1() {
  SomeClass mock = mock(SomeClass.class);
  when(mock.methodToTest(any()).thenCallRealMethod();
  when(mock.checkData(any()).thenReturn(true);

  List<String> result = mock.methodToTest(new SomeData()); // NullPointerException at someService.getData() call
  verify(someService).getData();
  assertEquals("Mock", result.get(0));
}

@Test
public void methodToTest_someServiceCalled2() {
  SomeClass someClass = new SomeClass(someService);
  List<String> result = someClass.methodToTest(new SomeData()); // Fails at checkData() call
  verify(someService).getData();
  assertEquals("Mock", result.get(0));
}

如何在模擬對父類 checkData() 的調用的同時為 someService 調用模擬? 不重構 SomeClass 有可能嗎?

如果您創建一個類的模擬,則其中不會有任何依賴項。 而是在真實實例上使用間諜。

這是一個工作示例。

@Mock
private SomeService someService;

@InjectMocks
private SomeClass classUnderTest;

@Before
public void setUp() {
    Mockito.when(someService.getData()).thenReturn(Collections.singletonList("Mock"));
}

@Test
public void methodToTest_someServiceCalled1() {

  SomeClass spy = Mockito.spy(classUnderTest);
  Mockito.when(spy.checkData(Mockito.any())).thenReturn(true);

  List<String> result = spy.methodToTest(new SomeData());
  Mockito.verify(someService).getData();
  assertEquals("Mock", result.get(0));
}

我不確定你是第二次測試,我會調用原始的checkData方法。 正如您所提到的,這是您想要避免的,解決方案應該類似於第一個測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM