模拟服务,不使用带Autowire的构造函数,但使用Java方法

模拟服务,不使用带Autowire的构造函数,但使用Java方法,java,spring,spring-boot,junit,junit5,Java,Spring,Spring Boot,Junit,Junit5,我想编辑此代码以使用mock for services。此代码工作正常: @Service public class BinCountryCheckFilterImpl { private RiskFilterService riskFilterService; private Terminals terminal; @Autowired public BinCountryCheckFilterImpl(Terminals terminal, RiskFilt

我想编辑此代码以使用mock for services。此代码工作正常:

@Service
public class BinCountryCheckFilterImpl {

    private RiskFilterService riskFilterService;
    private Terminals terminal;

    @Autowired
    public BinCountryCheckFilterImpl(Terminals terminal, RiskFilterService riskFilterService) {  
        this.terminal = terminal;
        this.riskFilterService = riskFilterService;
    }

    public void validateBinCountryCheckFilter(Terminals terminal) throws JAXBException, JsonProcessingException {

        List<RiskFilters> filter_list = riskFilterService.findRiskFiltersByTerminalIdAndType(terminal.getId(), "BinCountryCheckFilter");
    }
}
此代码不起作用:

    @Service
public class BinCountryCheckFilterImpl {

    @Autowired
    @Qualifier("riskFilterService")
    private RiskFilterService riskFilterService;

    public Response validateBinCountryCheckFilter(Merchants merchant, Contracts contract, Terminals terminal,
              PaymentTransaction message, HttpServletRequest request) throws JAXBException, JsonProcessingException {
               ...........

    }

}
由于某些原因,当我运行JUnit测试时,riskFilterService为null。有没有办法通过JUnit测试正确地实现服务? 在我的例子中,我不想从构造函数调用terminal,而是从Java方法validateBinCountryCheckFilter。。。和riskFilterService作为自动连线服务

singleton bean BinCountryCheckFilterImpl不能将每请求值终端作为字段,即在部署代码时作为构造函数上的参数,但它正在使用JUnit测试。如果终端值必须作为方法参数传递,JUnit代码将不会运行


您能给我一些建议吗?

我假设您正在使用JUnit4。最简单的方法是像这样使用MockitoJUnitRunner:

@RunWith(MockitoJUnitRunner.class)
public class BinCountryCheckFilterImplTest {

    @InjectMocks
    private BinCountryCheckFilterImpl binCountryCheckFilter;

    @Mock
    private RiskFilterService riskFilterService;


    @Test
    public void testBinCountryCheckFilterImpl() {
        // test content
    }

}
要使用JUnit5,您需要将@RunWithMockitoJUnitRunner.class更改为@ExtendWithMockitoExtension.class。当然,像@Test这样的其他东西也需要来自JUnit5。但是,Mockito@InjectMocks和@Mock注释与JUnit4相同

但是,在使用模拟服务调用构造函数之后,也可以使用Spring org.springframework.test.util.ReflectionTestUtils来设置字段。我更喜欢第一种方法而不是反射,但这更接近于您当前的代码

riskFilterService = Mockito.mock(RiskFilterService.class);
binCountryCheckFilter = new BinCountryCheckFilterImpl();
ReflectionTestUtils.setField(binCountryCheckFilter, "riskFilterService", riskFilterService);

将现有代码更改为:

public class BinCountryCheckFilterImpl {
    private final RiskFilterService riskFilterService;

    public BinCountryCheckFilterImpl(@Qualifier("riskFilterService") RiskFilterService riskFilterService) {
        this.riskFilterService = riskFilterService;
    }


    public void validateBinCountryCheckFilter(......) throws JAXBException, JsonProcessingException {
                   .........................
        }
}

是的,我想,这就是答案。谢谢你的回答。你能给我看看JUnit 5的解决方案吗?我添加了JUnit 5所需的更改。我有一个问题:@InjectMocks private BinCountryCheckFilterImpl binCountryCheckFilter;我添加了一个由BinCountryCheckFilterImpl实现的接口BinCountryCheckFilter。在这种情况下,我必须如何更改它?您只需模拟接口,而不是类@mock BinCountryCheckFilter BinCountryCheckFilter。Mockito扩展和/或实现传递给它的任何内容。它可以模拟任何非静态或最终的类/接口/方法。
public class BinCountryCheckFilterImpl {
    private final RiskFilterService riskFilterService;

    public BinCountryCheckFilterImpl(@Qualifier("riskFilterService") RiskFilterService riskFilterService) {
        this.riskFilterService = riskFilterService;
    }


    public void validateBinCountryCheckFilter(......) throws JAXBException, JsonProcessingException {
                   .........................
        }
}