在不使用Autowire构造函数的情况下模拟服务,但使用Java方法

时间:2019-11-02 21:15:04

标签: java spring spring-boot junit junit5

我想编辑此代码以将模拟用于服务。这段代码可以正常工作:

@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");
    }
}

JUnit测试:

public class BinCountryCheckFilterImplTest    {

    @Test
    public void testBinCountryCheckFilterImpl() throws JsonProcessingException, JAXBException {
        //Arrange
        RiskFilterService riskFilterService = Mockito.mock(RiskFilterService.class);
        Terminals terminal = Mockito.mock(Terminals.class);

        BDDMockito.given(
            riskFilterService.findRiskFiltersByTerminalIdAndType(anyInt(), anyString()))
            .willReturn(riskFiltersList);

        int expectedInt = 11;
        String expectedString = "BinCountryCheckFilter";

        when(terminal.getId()).thenReturn(expectedInt);

        BinCountryCheckFilterImpl binCountryCheckFilterImpl = 
            new BinCountryCheckFilterImpl(terminal, riskFilterService);

        //Act
        binCountryCheckFilterImpl.validateBinCountryCheckFilter();

        //Assert
        then(riskFilterService)
          .should()
          .findRiskFiltersByTerminalIdAndType(expectedInt, expectedString);
    }    
}

此代码不起作用:

    @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作为自动装配服务调用。

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

可以请教吗?

2 个答案:

答案 0 :(得分:4)

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

@RunWith(MockitoJUnitRunner.class)
public class BinCountryCheckFilterImplTest {

    @InjectMocks
    private BinCountryCheckFilterImpl binCountryCheckFilter;

    @Mock
    private RiskFilterService riskFilterService;


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

}

要使用JUnit 5,您需要将@RunWith(MockitoJUnitRunner.class)更改为@ExtendWith(MockitoExtension.class)。当然,使用的其他任何类似@Test都需要来自JUnit5。但是,Mockito @InjectMocks@Mock批注与JUnit 4相同。

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

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

答案 1 :(得分:0)

将现有代码更改为:

public class BinCountryCheckFilterImpl {
    private final RiskFilterService riskFilterService;

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


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