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

Java 使用构造函数注入模拟spring类,java,spring,unit-testing,mockito,Java,Spring,Unit Testing,Mockito,我有以下课程: @Service public class SomeClass extends BaseClass { private final SomeService someService; public SomeClass(SomeService someService) { this.someService = someService; } public List<String> methodToTest(SomeDataClass data)

我有以下课程:

@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();
  }
}
但是,我在创建testcase#2时遇到了问题。我可以使用
SomeClass SomeClass=new SomeClass(mockSomeService)
手动创建SomeClass,但是我需要为扩展checkData()请求创建模拟数据,我实际上不想在这个测试用例中测试它,因为它已经被一个不同的测试所覆盖,并且需要大量不必要的模拟,或者我可以模仿testcase#1中的某个类,但不管我怎么做,某个服务总是空的

我尝试了@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));
}
@Mock
私人服务;
@以前
公共作废设置(){
someService=mock(someService.class);
when(someService.getData()).thenReturn(Collections.singletonList(“Mock”));
}
@试验
public void methodToTest_someServiceCalled1(){
SomeClass mock=mock(SomeClass.class);
when(mock.methodToTest(any()).thenCallRealMethod();
when(mock.checkData(any())。然后返回(true);
List result=mock.methodToTest(new SomeData());//调用someService.getData()时出现NullPointerException
验证(someService).getData();
assertEquals(“Mock”,result.get(0));
}
@试验
public void methodToTest_someServiceCalled2(){
SomeClass SomeClass=新的SomeClass(someService);
List result=someClass.methodToTest(new SomeData());//在checkData()调用时失败
验证(someService).getData();
assertEquals(“Mock”,result.get(0));
}

如何在模拟对父类checkData()的调用的同时调用someService的mock?是否可以不重构SomeClass?

如果创建类的mock,则其中不会有任何依赖项。而是在真实实例上使用spy

下面是一个工作示例

@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));
}
@Mock
私人服务;
@注射模拟
测试中的私有类;
@以前
公共作废设置(){
Mockito.when(someService.getData()).thenReturn(Collections.singletonList(“Mock”);
}
@试验
public void methodToTest_someServiceCalled1(){
SomeClass spy=Mockito.spy(classUnderTest);
Mockito.when(spy.checkData(Mockito.any())。然后返回(true);
List result=spy.methodToTest(new SomeData());
验证(someService.getData();
assertEquals(“Mock”,result.get(0));
}


我不确定你是否是第二次测试,好吧,我会调用原始的
checkData
方法。正如你提到的,这是你想要避免的,解决方案应该与第一次测试类似。

你可能想使用
spy
。你能添加你尝试编写的测试吗?@第二次我添加了我已经添加的测试Ed您想测试
SomeService
不要模拟它,而是模拟依赖项。@MDeinum否,他们不想测试
SomeService
-他们想测试
getData()
被调用。正确的方法是对
SomeClass
进行间谍,对
SomeService
进行模拟。这实际上非常有效。谢谢。我知道不调用checkData是“错误的”,因为它是方法契约的一部分,但由于它被许多类调用,所以我决定对它进行显式测试,而不是在所有派生类中使用模拟数据。
@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));
}