我发现与Mockito嘲笑的任何例子与此类似(这些只是代码管理):
假设:
public interface MyInterface {
public String doWhatever();
}
public class MyClass {
@Autowired
MyInterface myInterface;
public String doSomething() {
return myInterface.doWhatever();
}
}
嘲讽:
@Mock
MyInterface myInterfaceMock;
@InjectMocks
MyClass myClass;
@Test
public void test() throws Exception {
when(myInterfaceMock.doWhatever()).thenReturn("foo");
String result = myClass.doSomething();
...
}
然而,在引入第二课时,使用更深层次:
public class MyOtherClass {
@Autowired
MyInterface myInterface;
public MyInterface getMyInterface() {
return myInterface;
}
}
更深层次模拟的类结构总是这样做:
public class MyClass {
MyOtherClass myOtherClass = new MyOtherClass();
public MyOtherClass getOtherClass() {
return myOtherClass;
}
}
@Test
public void test() throws Exception {
given(myClass.getOtherClass().getMyInterface().doSomething()).willReturn("bar");
String result = myClass.getOtherClass().getMyInterface().doSomething();
}
有关更多information
的信息,请参阅此深层存根示例但是,这并不反映我应该测试的班级结构。给定的结构如下:
public interface MyInterface {
public String doWhatever();
}
public class MyOtherClass {
@Autowired
MyInterface myInterface;
public String doOtherThing() {
return myInterface.doWhatever();
}
}
public class MyClass {
MyOtherClass myOtherClass = new MyOtherClass();
public String doSomething() {
return myOtherClass().doOtherThing();
}
}
现在,我想嘲笑它类似于:
@Mock
MyInterface myInterfaceMock;
@InjectMocks
MyClass myClass;
@Test
public void test() throws Exception {
when(myInterfaceMock.doWhatever()).thenReturn("foo");
String result = myClass.doSomething();
...
}
当然,这不起作用,因为模拟必须在MyOtherClass中注入,而不是在MyClass中注入。但是,如果我将它注入MyOtherClass,我没有MyClass的实例。
编辑:
引起我这个问题的原因是,我应该做微服务水平测试。可能是,我有错误的做法。我也可以通过模拟MyOtherClass测试单元测试MyClass,并通过模拟MyInterface对单元测试MyOtherClass进行测试。
因此,这里有一些关于给定微服务的更多细节:
REST-API - > SomeCode - > SomeOtherCode - >其他-REST-API
Out代码涵盖REST-API,SomeCode和SomeOtherCode。其他-REST-API是第三方,如谷歌,移动服务提供商等。
现在,我能够使用MockMVC测试REST-API并模拟SomeCode。而且我可以通过模拟Other-REST-API对SomeOtherCode进行单元测试。但是,我的目标是使用MockMVC测试整个链,进行一些参数变化并模拟Other-TEST-API,以查看SomeCode和SomeOtherCode的行为。
答案 0 :(得分:0)
所以发生的事情是@InjectMocks
模拟正在寻找注入MyClass
内的自动装配的东西时,MyClass
没有,所以它找不到任何东西。
如果MyOtherClass
为@Autowired
,我怀疑这会有用,但您可能也需要为@InjectMocks
执行MyOtherClass
。
答案 1 :(得分:0)
根据您的更新: 您应该看看https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html - 在这里您可以看到如何运行集成测试。您可以提供自己的spring-xml
@ContextConfiguration("/test-config.xml")
public class XmlApplicationContextTests {
// class body...
}
或弹簧配置测试中的一个类。
@ContextConfiguration(classes = TestConfig.class)
public class ConfigClassApplicationContextTests {
// class body...
}
此外,您可以使用
为xml定义模拟和间谍<bean id="spyService" class="org.mockito.Mockito" factory-method="spy">
<constructor-arg ref="service"/>
</bean>
<bean id="mockService" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="your.Service" />
</bean>
或配置
@Configuration
static class TestConfig {
@Bean
Service serviceMock() {
return mock(Service.class);
}
@Bean
Service serviceSpy() {
return spy(new Service());
}
}
但实际上这就是你用spring进行集成测试的方法。
在这种情况下,您还需要提供正确的UnitTestRunner SpringJUnitRunner。你应该得到类似的东西:
@RunWith(SpringJUnitRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class MyClassComponentTest {
@Autowired
MyInterface myInterfaceMock;
@Autowired
MyClass myClass;
@Configuration
static class TestConfig {
@Bean
MyClass myClass() {
return new MyClass();
}
@Bean
MyOtherClass myOtherClass() {
return new MyOtherClass();
}
@Bean
MyInterface myInterfaceMock() {
return mock(MyInterface.class);
}
}
@Test
public void test() throws Exception {
when(myInterfaceMock.doWhatever()).thenReturn("foo");
String result = myClass.doSomething();
...
}
}
旧回答
问题是:&#34;实际上是否想要进行单元测试?&#34;
因为当你进行单元测试时,你根本不在乎什么 发生在
MyOtherClass
内。你只需要模拟MyOtherClass, 并为你嘲笑的MyOtherClass
写一个自己的UnittestMyInterface
。我在你的例子中看到的另一个问题是,你永远不会 实例化一个类
MyOtherClass
的对象,那个是 永远不会注入你的MyClass
- 对象,所以实际上并没有 工作