Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring @注入@MockBean的@Service中的字段上的值将导致null值_Spring_Spring Boot_Mocking_Mockito_Spring Boot Test - Fatal编程技术网

Spring @注入@MockBean的@Service中的字段上的值将导致null值

Spring @注入@MockBean的@Service中的字段上的值将导致null值,spring,spring-boot,mocking,mockito,spring-boot-test,Spring,Spring Boot,Mocking,Mockito,Spring Boot Test,我有以下服务: @服务 公共类MyService{ @值(${my.Value}) 私有字符串myValue; 公共字符串SomeMethodwhichuseMyValueField(){ 返回myValue; } //还包含使用通过` RestTemplate'访问的某些外部服务的其他方法` } 这个集成测试: @RunWith(SpringRunner.class) @SpringBootTest(类=MyApplication.class) 公共类MyControllerTest{ 私有

我有以下服务:

@服务
公共类MyService{
@值(${my.Value})
私有字符串myValue;
公共字符串SomeMethodwhichuseMyValueField(){
返回myValue;
}
//还包含使用通过` RestTemplate'访问的某些外部服务的其他方法`
}
这个集成测试:

@RunWith(SpringRunner.class)
@SpringBootTest(类=MyApplication.class)
公共类MyControllerTest{
私有MockMvc myControllerMockMvc;
@自动连线
私有MyController MyController;//此控制器注入MyService的实例
@蚕豆
私有MyService-myservicecomck;
@以前
公共作废设置(){
this.myControllerMockMvc=MockMvcBuilders.standaloneSetup(myController.build();
当(myServiceMock.SomeMethodwhichuseMyValueField()).thenCallRealMethod()时;
//还要模拟myServiceMock中调用外部Web服务的其他方法
}
@试验
public void someTest()引发异常{
//使用myControllerMockMvc调用调用myService.SomeMethodWhichUsersMyValueField()的POST方法
}
}
问题在于,当从
someTest()
方法调用
myService.somemethodwhichusemyvaluefield()
方法时,字段
myValue
(以及所有用
@Autowired
注释的字段)即使我的
应用程序.properties
正确定义了
my.value=some值,也为
null


是否有一种方法可以像任何普通的
@Autowired
组件一样,正确地使
myValue
注入
应用程序中描述的值。属性

您可以在测试类中设置属性

@TestPropertySource(properties = {"my.value=value"})
public class MyControllerTest {
//
}

使用
@SpyBean
而不是
@MockBean
,因为这样您就可以为真正的Spring对象注入一些可以模拟的方法(感谢
@Spy
提示):

/[…]注释中没有要更改的内容
公共类MyControllerTest{
//[…]在其他领域没有任何变化
@间谍
私有MyService-myservicecomck;
@以前
public void setup()引发NoSuchFieldException,IllegalAccessException{
//[…]嘲笑之前没有什么可以改变的
//然后,不要再使用.thenCallRealMethod()进行模拟,这是spy的默认行为
//在模拟myServiceMock中调用外部Web服务的其他方法时,请使用以下声明:
doAnswer(调用->/*回复某物*/).when(myServiceMock).someMethodwhichusExternalWebService(any());
//而不是when(myServiceMock.someMethodwhichusExternalWebService(any())。然后回答(调用->/*回复某物*/);
}
//[…]试验方法无需更改
}
另一种(丑陋的?)方法是直接从测试类手动注入字段,例如:

/[…]注释中没有要更改的内容
公共类MyControllerTest{
//[…]在其他领域没有任何变化
@值(${my.Value})
私有字符串myValue;
@以前
public void setup()引发NoSuchFieldException,IllegalAccessException{
ReflectionTestUtils.setField(myServiceMock,“myValue”,myValue);//感谢@thomas andolf的[answer](https://stackoverflow.com/a/55148170/535203)
////与传统反射工具等效:
//字段myValueField=MyService.class.getDeclaredField(“myValue”);
//myValueField.setAccessible(true);
//myValueField.set(myServiceMock,myValue);
//[…]原始方法的其余部分
}
//[…]试验方法无需更改
}

解决此问题的两种方法如下,您可以使用:

构造函数注入:

@Service
public class MyService {

    private final myValue;

    public MyService(@Value("${my.value}") myValue) {
        this.myValue = myValue;
    }

    public String someMethodWhichUsesMyValueField() {
        return myValue;
    }
}
不要使用mock,只需使用类并将其值提供给它即可

或者您可以使用:

ReflectionTestUtils.setField(myService, "myValue", "FooBar");
将myValue属性设置为foobar


或者你可以改为使用@Spy,这是一个“部分模拟”。spy是具有原始方法的原始类,然后您可以选择模拟某些方法,但保留某些方法中原始类的逻辑。

我尝试在my
MyControllerTest
上添加此注释,但没有任何效果:
myValue
inside
myService
仍然有效
null
@AnthonyO。您可以使用
@MockBean-MyService-myservicecomock
。这意味着spring创建了一个模拟而不是一个对象。你必须自动连接itOK,但这不是你的答案,是吗?我试图在
MyControllerTest
中的
myServiceLock
字段中添加
@Autowired
,但没有成功。我还试图在我的
@MockBean-MyService-MyService-myservicecemock
之外添加一个字段
@Autowired-MyService-MyService-MyService
,但这两个对象是同一个实例:mock对象。@Samim不,它不起作用,因为这里
myservicecemock
注入了
@MockBean
,但没有包含
@Value
价值观