我有一堆服务类,它们看起来都很像或类似。
@Service
public class ServiceA {
private RepositoryA repA;
private RepositoryB repB;
private DependencyC depC;
private DependencyD depD;
private ServiceB serviceB;
@Autowired
public ServiceA(RepositoryA repA, RepositoryB repB, DependencyC depC, DependencyD depD, ServiceB serviceB) {
this.repA = repA;
....
}
}
现在,我想在不启动Spring的情况下在测试类中使用这些服务。如果我在应用程序上下文中使用bean,测试会花费太长时间。我想模拟服务类,但由于嵌套结构太深,我不知道如何模拟。简单的方法是模拟ServiceA使用的所有存储库、依赖项和服务,并将它们自己注入测试类中,但这似乎不对,因为我必须对ServiceB做同样的事情。
您可以使用mockito进行此操作,然后您的代码将类似于此
@RunWith(MockitoJUnitRunner.Silent.class)
public class ServiceATest {
@Mock
RepositoryA repA;
@Mock
RepositoryB repB;
@Mock
DependencyC depC;
@Mock
DependencyD depD;
@Mock
ServiceB serviceB;
@InjectMocks
ServiceA serviceA;
}
然后,当您需要在测试中使用mock时,您可以模拟模拟类的方法,例如:
@Test
public void someTest() {
...
when(repA.repMethod()).thenReturn(new SomeObject());
SomeObject mockedObject = serviceA.serviceMethod(); // if serviceMethod call repMethod, you will get the object which you passed in youк mock method call
...
}
两种选择:
- 模拟
ServiceB
- 按照您所描述的操作,因为您无论如何都要这样做,以便为
ServiceB
编写测试,以便重用该工作 - 构建一个充满mock的替代Spring上下文,并将其用于测试
我通常选择2。它是不纯净的,因为ServiceA
的正确性取决于ServiceB
的正确性,但编写、管理和理解的测试代码较少。
public class ServiceATest {
private RepositoryA repA;
private RepositoryB repB;
private DependencyC depC;
private DependencyD depD;
private ServiceB serviceB;
@Before
public void init() {
this.repB = mock(RepositoryA.class);
.....
// mock all repositories you need.
this.serveceB = new ServiceB(repoB,...);
//then use contructor method to instantiate serviceB. Also do same with
//serviceB
this.serviceA = new ServiceA(repA, repB,depC, depD, serviceB)
}
//Write the tests like that
@Test
public void saveanything_shouldBeCorect() {
when(repoA.save()any()).thenReturn(mySavedMock);
MyVariable resp = serviceA.save(myMock);
// them assert your resp.
}
}
重要的是使用mockito方法";当(rep.anython(any((((仅在已移动到init方法的存储库中时。