简体   繁体   English

使用构造函数注入模拟 spring 类

[英]Mocking a spring class with constructor injection

I have the following class:我有以下课程:

@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();
  }
}

I now want to create testcases for SomeClass using Mockito.我现在想使用 Mockito 为 SomeClass 创建测试用例。

  1. Test that checkData() is called.测试是否调用了 checkData()。
  2. Test that someService.getData() is called.测试 someService.getData() 是否被调用。

Using Mockito, I've managed testcase 1 with:使用 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());
}

However, I have problems creating testcase #2.但是,我在创建测试用例 #2 时遇到了问题。 I can either create SomeClass manually with SomeClass someClass = new SomeClass(mockSomeService) , but then I need to create mock data for the extensive checkData() request, which I don't actually want to test in this testcase since it's already covered by a different test and which requires a lot of unnecessary mocking, or I can mock SomeClass like in testcase #1, but then someService is always null, no matter what I try.我可以使用SomeClass someClass = new SomeClass(mockSomeService)手动创建 SomeClass ,但随后我需要为广泛的 checkData() 请求创建模拟数据,我实际上并不想在这个测试用例中进行测试,因为它已经被一个不同的测试,这需要很多不必要的模拟,或者我可以像测试用例 #1 那样模拟 SomeClass,但是无论我尝试什么, someService 始终为空。

I've tried variations of @InjectMocks, @Mock and such, but I've failed to create a workable solution.我尝试过@InjectMocks、@Mock 等的变体,但我未能创建一个可行的解决方案。

Things I've tried:我尝试过的事情:

@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));
}

How can I have a call a mock for someService while still mocking the call to the parent classes checkData()?如何在模拟对父类 checkData() 的调用的同时为 someService 调用模拟? Is it possible without refactoring SomeClass?不重构 SomeClass 有可能吗?

If you create a mock of a class there won't be any dependencies in it.如果您创建一个类的模拟,则其中不会有任何依赖项。 Instead use a spy on a real instance.而是在真实实例上使用间谍。

Here is a working example.这是一个工作示例。

@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));
}

I am not sure about you're 2nd test, afaik I would call the original checkData method.我不确定你是第二次测试,我会调用原始的checkData方法。 As you mentioned that is something you want to avoid, the solution should be similiar to the 1st test.正如您所提到的,这是您想要避免的,解决方案应该类似于第一个测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM