Java 假装没有被注射

Java 假装没有被注射,java,junit,mockito,Java,Junit,Mockito,我试图为单元测试注入一个mock,但我一直得到一个null点异常 下面是我要测试的类,空指针似乎带有ParameterFacade 当我运行测试时,它似乎没有注入mock,因为参数facade为null @Service public class PostUnderwriterTransactionProcessProvider extends AbstractProcessProvider<PostUnderwriterTransactionInput> { @Autow

我试图为单元测试注入一个mock,但我一直得到一个null点异常

下面是我要测试的类,空指针似乎带有ParameterFacade

当我运行测试时,它似乎没有注入mock,因为参数facade为null

@Service
public class PostUnderwriterTransactionProcessProvider extends AbstractProcessProvider<PostUnderwriterTransactionInput> {

    @Autowired
    private ParameterFacade parameterService;

    @Override
    public Page startProcess(PostUnderwriterTransactionInput processInput) {

        final PostUnderwriterTransactionContext context = new PostUnderwriterTransactionContext(processInput.getPolicy(),
                setupStrataContextModel(POST_TRANSACTIONS),
                processInput.getTransactionsTypes(),
                processInput.getParameterSelectionCriteria(),
                parameterService.shouldApplyCommissionFromPolicy());

        context.setPostingFromInput(processInput.getAccount().getBalance(),
                processInput.getAccount().getID(),
                getBranch(),
                processInput.getPolicy(),
                processInput.getProcess(),

                null);

        return new AdhocTransactionPostingPage(new TransactionPostingContextModel(context));
    }

}
@服务
公共类postenderWriterTransactionProcessProvider扩展了AbstractProcessProvider{
@自动连线
私有参数facade参数服务;
@凌驾
公共页面启动进程(PostanderWriterTransactionInputProcessInput){
final postenderWriterTransactionContext=新的postenderWriterTransactionContext(processInput.getPolicy(),
setupStrataContextModel(后交易),
processInput.getTransactionsTypes(),
processInput.getParameterSelectionCriteria(),
parameterService.shouldApplyCommissionFromPolicy());
context.setPostingFromInput(processInput.getAccount().getBalance(),
processInput.getAccount().getID(),
getBranch(),
processInput.getPolicy(),
processInput.getProcess(),
无效);
返回新的AdhocTransactionPostingPage(新的TransactionPostingContextModel(上下文));
}
}
测试是

@RunWith(MockitoJUnitRunner.class)
public class PostUnderwriterTransactionProcessProviderTest extends WicketTestCase {

    @ClassRule
    public static MetadataServiceRule metadataServiceRule = new MetadataServiceRule();

    @Mock
    private ParameterFacade mockParameterService;

    @InjectMocks
    private PostUnderwriterTransactionProcessProvider testSubject;


    @Before
    public void setup() {
        tester.putBean(mockConversationScopeManager);
        testSubject = new PostUnderwriterTransactionProcessProvider();
        policy = PolicyTestDataBuilder.aPolicy().build();
        account = createAccount();
        testSubject.setUserInfoProvider(MockUserInfoPartyProvider.getMockUserInfoProvider());
        testSubject.setSystemPartyFacade(MockUserInfoPartyProvider.getMockSystemPartyFacade());
        testSubject.setCodeModelFacade(codeModelFacade);
    }

    @Test
    public void startProcessShouldCreateAdhocTransactionPostingPage() {
        // Given
        when(mockParameterService.shouldApplyCommissionFromPolicy()).thenReturn(true);
        final ParameterSelectionCriteriaModel pscm = new ParameterSelectionCriteriaModel();
        final List<TransactionTypeModel> transactions = createTransactionsTypes();
        final PostUnderwriterTransactionInput input = new PostUnderwriterTransactionInput(policy, account, pscm, transactions);

        // When
        final Page page = testSubject.startProcess(input);

        // Then
        assertThat(page, instanceOf(AdhocTransactionPostingPage.class));
        assertThat("Page Default Model is: ", page.getDefaultModelObject(), instanceOf(PostUnderwriterTransactionContext.class));
        assertPageContextValues(page);
    }
}
@RunWith(MockitoJUnitRunner.class)
公共类postenderWriterTransactionProcessProviderTest扩展了WicketTestCase{
@阶级规则
公共静态MetadataServiceRule MetadataServiceRule=新MetadataServiceRule();
@嘲弄
私有参数服务;
@注射模拟
私有postenderWriterTransactionProcessProviderTestSubject;
@以前
公共作废设置(){
putBean(mockConversationScopeManager);
testSubject=new postenderWriterTransactionProcessProvider();
policy=PolicyTestDataBuilder.aPolicy().build();
account=createAccount();
testSubject.setUserInfoProvider(MockUserInfoPartyProvider.getMockUserInfoProvider());
testSubject.setSystemPartyFacade(MockUserInfoPartyProvider.getMockSystemPartyFacade());
setCodeModelFacade(codeModelFacade);
}
@试验
public void startProcess应创建AdhocTransactionPostingPage(){
//给定
when(mockParameterService.shouldApplyCommissionFromPolicy())。然后返回(true);
最终参数SelectionCriteriaModel pscm=新参数SelectionCriteriaModel();
最终列表事务=createTransactionsTypes();
final postenderWriterTransactionInput=新的postenderWriterTransactionInput(策略、账户、pscm、交易);
//什么时候
最终页面=testSubject.startProcess(输入);
//然后
断言(第页,instanceOf(AdhocTransactionPostingPage.class));
断言(“页面默认模型为:”,Page.getDefaultModelObject(),instanceOf(postenderWriterTransactionContext.class));
assertPageContextValues(第页);
}
}
线路

 testSubject = new PostUnderwriterTransactionProcessProvider();
正在重写用创建的实例

@InjectMocks
private PostUnderwriterTransactionProcessProvider testSubject;
删除手动初始化以使框架按设计运行

否则,如果您想手动注入依赖项,则考虑重构类遵循显式依赖原则

@Service
public class PostUnderwriterTransactionProcessProvider 
    extends AbstractProcessProvider<PostUnderwriterTransactionInput> {

    private final ParameterFacade parameterService;

    @Autowired
    public PostUnderwriterTransactionProcessProvider(ParameterFacade parameterService) {
        this.parameterService = parameterService;
    }

    //...omitted for brevity

}

看看下面的代码,让我们看看每一行都做了什么-

@Mock
private ParameterFacade mockParameterService; //1

@InjectMocks
private PostUnderwriterTransactionProcessProvider testSubject; // 2


@Before
public void setup() {
    testSubject = new PostUnderwriterTransactionProcessProvider(); //3
}
1
使用spring框架的
@Mock
注释。这告诉spring模拟类型为
ParameterFacade
的对象,创建一个模拟的实例,并将其保存在
mockParameterService
变量中

2
使用
@InjectMocks
注释,该注释告诉spring使用在该测试中创建的模拟对象(我们在行
1
中创建了该对象),并在创建它时将其用作变量
testSubject
中的依赖项。这将导致
testSubject
包含
postenderWriterTransactionProcessProvider
实例,该实例的依赖项为模拟类型
ParameterFacade
注入到他身上


3行
创建了
postenderWriterTransactionProcessProvider的新实例
。这是纯java,没有spring,没有模拟,没有依赖。只需按照java的常规方式创建该类型的新实例。在
2
中创建的实例被这个新的普通实例替换,并且在某种程度上,任何断言都会覆盖以前的值,这使得变量
testSubject
保存这个对象

对提供的答案有任何反馈吗?
    1. ParameterFacade is a spring container managed bean (as it is annotated with @Service and other spring annotations like @Autowired).
    2. @RunWith is configured to use MockitoJUnitRunner which cannot instantiate spring managed container beans

    Hence, in order to handle bean lifecycle in unit tests you'll need to
    1. Use @RunWith(SpringJUnit4ClassRunner.class)
    2. Annotate PostUnderwriterTransactionProcessProvider with @Autowired.
    3. Change @Mock to @MockBean on ParameterFacade (org.springframework.boot.test.mock.mockito.MockBean)
@Mock
private ParameterFacade mockParameterService; //1

@InjectMocks
private PostUnderwriterTransactionProcessProvider testSubject; // 2


@Before
public void setup() {
    testSubject = new PostUnderwriterTransactionProcessProvider(); //3
}