Java 对Mockito Mock的链接方法调用返回Null
我有一个带有注入对象的@Component,它通过链式方法调用来获取一些东西,例如Java 对Mockito Mock的链接方法调用返回Null,java,unit-testing,mocking,mockito,method-chaining,Java,Unit Testing,Mocking,Mockito,Method Chaining,我有一个带有注入对象的@Component,它通过链式方法调用来获取一些东西,例如 @Component public class MyInterceptor implements ClientHttpRequestInterceptor { @Autowired public MyProducer producer; @Override public ClientHttpResponse intercept(…) throws IOException { Strin
@Component
public class MyInterceptor implements ClientHttpRequestInterceptor {
@Autowired
public MyProducer producer;
@Override
public ClientHttpResponse intercept(…) throws IOException {
String val = producer.getProducer().getSomeVal(/*parameters*/); // LINE (1)
}
}
我的测试课程是:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { MyInterceptor.class, MyProducer.class } )
public class MyInterceptorTest {
private RestTemplate restTemplate = new RestTemplate();
private MockRestSErviceServer mockServer;
@Rule
public MockitoRule rule = MockitoJUnit.rule();
@Mock
public MyProducer producer;
@InjectMocks
private MyInterceptor interceptor;
@Before
public void init() {
//MockitoAnnotation.initMocks(this);
producer = Mockito.mock(MyProducer.class, Mockito.RETURNS_DEEP_STUBS);
// adding interceptor to RestTemplate
mockServer = MockRestServiceServer.createServer(restTemplate);
when(producer.getProducer().getSomeVal(null, null)).thenReturn("SomeValue");
}
@Test
public void myTestMethod() {
mockServer.expect(requestTo(/*some dummy URL*/)
.andExpect(method(HttpMethod.GET))
.andExcept(/*some header stuff omitted from MyInterceptor */)
.andRespond(withSuccess(/*…*/));
// This is going to trigger the Interceptor being invoked
restTemplate.getForEntity("some dummy URL", String.class); // LINE (2)
mockServer.verify();
}
}
当测试执行第2行并调用拦截器时,在第1行我得到一个空指针异常
我的假设是,通过在模拟上启用深度存根,我将能够进行链式调用并获得预期值,例如producer.getProducer.getSomeVal,但事实似乎并非如此
你知道我怎样才能让它按预期工作吗
另外,我尝试了添加MockitoAnnotation.initMocks和在测试类中去掉@Rule,或者只去掉@Autowired MyInterceptor的不同变体,这使得MyProducer根本不被模仿,但似乎没有任何效果
请注意,不能修改MyProducer,因为它来自另一个项目。您模拟了MyProducer类,但没有为producer.getProducer提供when
因此,当代码调用producer.getProducer时,它将返回默认的模拟值,即null
您可以尝试几种不同的方法:
when(producer.getProducer()).thenReturn(producer);
我不确定这是否行得通——也许行
否则,您可以编写一个本地测试类,实现/扩展getProducer返回的任何内容,当正确的参数传递给getSomeVal时,该类将返回相应的测试值。MyInterceptorintercept调用producer.getProducer.getSomeVal,我认为启用带有返回\u DEEP\u存根的方法链接可以解决这个问题。现在,正如你所说的,我需要补充什么才能使这项工作顺利进行?我不能执行doReturn/*某些生产者*/。whenproducer.getProducer然后下一行whenproducer.getSomeValnull,null.thenReturnSomeValue会抱怨返回类型错误。即使我执行producer=doReturn/*某些生产者*/。whenproducer.getProducer,whenfromProducer.getSomeVal/*…*/。thenReturnSomeValue,fromProducer仍然为空。我甚至尝试了producer=doAnswernew Answer{/*…*/}中的某个对象。whenproducer.getProducer具有相同的结果。编辑以提供潜在的解决方案。调用producer.getProducer不会返回MyProducer,但正如我在前面的评论中提到的,它返回另一个我称为getSomeVal的对象。不管怎样,我尝试了建议的路线,它仍然抛出NPE。我所做的是,和你的一样,我去掉了producer=Mockito.mockMyProducer.class,Mockito.RETURNS\u DEEP\u STUBS;总之,应用程序在较低的环境中为producer.getProducer提供了一个静态变量,我用它返回,然后用它调用getSomeVal,这就成功了。你能把intercept的实现分成两行吗?第一个是producer.getProducer,第二个是.getSomeVal调用?然后使用调试器,查看哪一个为您提供空指针异常。@Jason,这将是producer.getProducer,它为空。