模拟弹簧值注入

2022-09-01 16:24:29

我正在尝试为以下方法编写测试类

public class CustomServiceImpl implements CustomService {
    @Value("#{myProp['custom.url']}")
    private String url;
    @Autowire
    private DataService dataService;

我在类中的一个方法中使用注入的url值。为了测试这一点,我写了一个 junit 类

@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-test.xml" })
public CustomServiceTest{
    private CustomService customService;
    @Mock
    private DataService dataService;
    @Before
    public void setup() {
        customService = new CustomServiceImpl();
        Setter.set(customService, "dataService", dataService);
    }    
    ...
}

public class Setter {
    public static void set(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

在 applicationContext-test 中.xml我正在加载属性文件

    <util:properties id="myProp" location="myProp.properties"/>

但是,在运行测试时,url 值不会加载到自定义服务中。我想知道是否有办法完成这项工作。

谢谢


答案 1
import org.springframework.test.util.ReflectionTestUtils;

@RunWith(MockitoJUnitRunner.class)
public CustomServiceTest{

@InjectMocks
private CustomServiceImpl customService;

@Mock
private DataService dataService;

@Before
public void setup() {
    ReflectionTestUtils.setField(customService, "url", "http://someurl");
}    
...
}

答案 2

我同意@skaffman的评论。

除了你的测试使用,因此它不会寻找任何Spring的东西,这个唯一的目的是初始化Mockito模拟。用弹簧连接东西是不够的。从技术上讲,使用JUnit,如果你想要与弹簧相关的东西,你可以使用以下运行器: 。MockitoJUnitRunnerContextConfigurationSpringJUnit4ClassRunner

此外,当您编写单元测试时,您可能需要重新考虑spring的使用。在单元测试中使用弹簧布线是错误的。但是,如果您正在编写集成测试,那么您为什么要在那里使用Mockito,这是没有意义的(正如skaffman所说)!

编辑:现在在你的代码中,你直接在你的之前块中设置,这也没有意义。春天根本不参与其中!CustomerServiceImpl

@Before
public void setup() {
    customService = new CustomServiceImpl();
    Setter.set(customService, "dataService", dataService);
}

编辑2:如果你想写一个 单元测试 ,那么避免Spring的东西,直接注入属性的值。您也可以使用 Mockito 将模拟直通注入到测试的实例中。CustomerServiceImplDataService

@RunWith(MockitoJUnitRunner.class)
public CustomServiceImplTest{
    @InjectMocks private CustomServiceImpl customServiceImpl;
    @Mock private DataService dataService;

    @Before void inject_url() { customServiceImpl.url = "http://..."; }

    @Test public void customerService_should_delegate_to_dataService() { ... }
}

您可能已经注意到,我正在使用对字段的直接访问,该字段可以是包可见的。这是一个测试解决方法,可以实际注入URL值,因为Mockito只注入模拟。url