Sam*_*nes 25 java spring unit-testing dependency-injection mockito
我有一个@Controller带有这个构造函数的Spring MVC :
@Autowired
public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/}
Run Code Online (Sandbox Code Playgroud)
我想为这个Controller编写一个独立的单元测试:
@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {
@Mock
private XyzService mockXyzService;
private String myProperty = "my property value";
@InjectMocks
private AbcController controllerUnderTest;
/* tests */
}
Run Code Online (Sandbox Code Playgroud)
有没有办法@InjectMocks注入我的String属性?我知道我不能模拟一个字符串,因为它是不可变的,但我可以在这里注入一个普通的字符串吗?
@InjectMocks在这种情况下,默认情况下会注入null.@Mock如果我戴上它,可以理解地抛出异常myProperty.是否有另外一个注释我错过了只是意味着"注入这个确切的对象而不是它的模拟"?
小智 30
您无法使用Mockito执行此操作,但Apache Commons实际上可以使用其内置实用程序之一来实现此目的.你可以将它放在JUnit中的一个函数中,该函数在Mockito注入其余的模拟之后但在测试用例运行之前运行,如下所示:
@InjectMocks
MyClass myClass;
@Before
public void before() throws Exception {
FieldUtils.writeField(myClass, "fieldName", fieldValue, true);
}
Run Code Online (Sandbox Code Playgroud)
jeb*_*det 17
由于您使用的是 Spring,因此您可以使用org.springframework.test.util.ReflectionTestUtils来自spring-test模块的 。它巧妙地包装了在对象上设置字段或在类上设置静态字段(以及其他实用程序方法)。
@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {
@Mock
private XyzService mockXyzService;
@InjectMocks
private AbcController controllerUnderTest;
@Before
public void setUp() {
ReflectionTestUtils.setField(controllerUnderTest, "myProperty",
"String you want to inject");
}
/* tests */
}
Run Code Online (Sandbox Code Playgroud)
你不能用Mockito做到这一点,因为,正如你自己提到的,a String是final和不能被嘲笑.
有一个@Spy注释适用于真实物体,但它有相同的限制@Mock,因此你不能窥探String.
没有注释告诉Mockito只是注入该值而不进行任何嘲弄或间谍活动.不过,这将是一个很好的功能.也许在Mockito Github存储库中建议它.
如果您不想更改代码,则必须手动实例化控制器.
进行基于纯注释的测试的唯一方法是重构控制器.它可以使用仅包含该属性的自定义对象,也可以使用具有多个属性的配置类.
@Component
public class MyProperty {
@Value("${my.property}")
private String myProperty;
...
}
Run Code Online (Sandbox Code Playgroud)
这可以注入控制器.
@Autowired
public AbcController(XyzService xyzService, MyProperty myProperty) {
...
}
Run Code Online (Sandbox Code Playgroud)
你可以模拟并注入它.
@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {
@Mock
private XyzService mockXyzService;
@Mock
private MyProperty myProperty;
@InjectMocks
private AbcController controllerUnderTest;
@Before
public void setUp(){
when(myProperty.get()).thenReturn("my property value");
}
/* tests */
}
Run Code Online (Sandbox Code Playgroud)
这不是很直接,但至少你可以通过一点点存根进行纯粹的基于注释的测试.
小智 5
在这种情况下不要使用@InjectMocks。
做:
@Before
public void setup() {
controllerUnderTest = new AbcController(mockXyzService, "my property value");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18429 次 |
| 最近记录: |