使用@InjectMocks 注入字符串属性

新手上路,请多包涵

我有一个带有此构造函数的 Spring MVC @Controller

 @Autowired
public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/}

我想为此控制器编写一个独立的单元测试:

 @RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    private String myProperty = "my property value";

    @InjectMocks
    private AbcController controllerUnderTest;

    /* tests */
}

有没有办法让 @InjectMocks 注入我的 String 属性?我知道我不能模拟一个字符串,因为它是不可变的,但我可以在这里注入一个普通的字符串吗?

@InjectMocks 在这种情况下默认注入一个空值。 @Mock 可以理解,如果我把它放在 myProperty 上会抛出异常。我错过了另一个注释,它只是意味着“注入这个确切的对象而不是它的模拟”吗?

原文由 Sam Jones 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

你不能用 Mockito 做到这一点,因为正如你自己提到的,a Stringfinal 并且不能被嘲笑。

有一个 @Spy 注释适用于 真实 对象,但它具有与 @Mock 相同的限制,因此您不能监视 String

没有注释告诉 Mockito 只注入该值而不进行任何模拟或监视。不过,这将是一个很好的功能。也许在 Mockito Github 存储库 中建议它。

如果您不想更改代码,则必须手动实例化您的控制器。

进行基于纯注释的测试的唯一方法是重构控制器。它可以使用仅包含该一个属性的自定义对象,或者可能使用具有多个属性的配置类。

 @Component
public class MyProperty {

    @Value("${my.property}")
    private String myProperty;

    ...
}

这可以注入到控制器中。

 @Autowired
public AbcController(XyzService xyzService, MyProperty myProperty) {
    ...
}

然后你可以模拟并注入它。

 @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 */
}

这不是很直接,但至少您可以通过一些存根来进行纯注释的测试。

原文由 Tom Verelst 发布,翻译遵循 CC BY-SA 3.0 许可协议

您不能使用 Mockito 执行此操作,但 Apache Commons 实际上有一种使用其内置实用程序之一执行此操作的方法。您可以将它放在 JUnit 中的一个函数中,该函数在 Mockito 注入其余模拟之后但在您的测试用例运行之前运行,如下所示:

 @InjectMocks
MyClass myClass;

@Before
public void before() throws Exception {
    FieldUtils.writeField(myClass, "fieldName", fieldValue, true);
}

原文由 Jacob Beasley 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题