我有一个Spring bean,让我们说:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class AImpl implements A {
public void setSomeDependency(D dependency) {
// This setter DOES NOT BELONG to interface A
}
}
<bean id="aImpl" class="AImpl"/>
Run Code Online (Sandbox Code Playgroud)
现在我想集成测试它,但首先我需要模拟依赖D,因为它做了太多的东西.由于AImpl实现了一个接口并包含一个事务注释,生成的代理只与接口兼容A,所以我可以这样做:
@Inject @Named("aImpl")
private A a;
Run Code Online (Sandbox Code Playgroud)
但不能:
@Inject @Named("aImpl")
private AImpl a;
Run Code Online (Sandbox Code Playgroud)
结果,我无法模仿我的依赖.
请注意,添加void setSomeDependency(D dependency)到界面A不是一个选项,因为它没有商业含义.它都没有使用proxy-target-class="true",因为它打破了很多其他bean(这个属性会影响上下文中的所有bean).
有没有办法解开注入的bean A,所以我可以把它投射到AImpl?
我需要通过类类型查找bean.当bean被代理包装时(某些方法是@Transactional) - ApplicatoinContext无法找到它们.我发现如果我通过接口查找它们,它可以工作,但在这种情况下,我正在使用具体的类类型.我知道bean是我正在寻找的类型,但getBean()方法失败.
我可以调试(并修复)Spring的AbstractBeanFactory代码中的问题.问题是它根据我要请求的类型检查beanInstance的类型,但beanInstance.getClass()是一个代理.AbstractBeanFactory应该对此进行补偿,并将类型与代理的目标类进行比较.
我有一个修复此问题,但我不是特别想使用修补版本的Spring,我怀疑必须有一些我可以配置来使这个工作,或者这真的是一个错误?
当我一起使用webAppContextSetup时,我很难让Mockito和MockMvc一起工作.我很好奇,如果是因为我以一种他们从未想过的方式混合这两者.
资料来源:https://github.com/zgardner/spring-boot-intro/blob/master/src/test/java/com/zgardner/springBootIntro/controller/PersonControllerTest.java
这是我正在运行的测试:
package com.zgardner.springBootIntro.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static java.lang.Math.toIntExact;
import static org.hamcrest.Matchers.is;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import com.zgardner.springBootIntro.Application;
import com.zgardner.springBootIntro.service.PersonService;
import com.zgardner.springBootIntro.model.PersonModel;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class PersonControllerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext; …Run Code Online (Sandbox Code Playgroud)