我以前使用过Spring DI,我认为其中一个好处是我可以在不涉及Spring的情况下测试我的Spring bean类(为简洁起见省略了导入):
public class Foo { private String field; public void setField(String field) { this.field = field; } public String getField() { return field; } } public class TestFoo { @Test public void test_field_is_set() { Foo foo = new Foo(); foo.setField("Bar"); assertEquals("Bar", foo.getField()); } }现在我正在尝试使用JSR-330,这意味着没有明确地编写setter。
到目前为止,我正在使用Hk2,纯粹是因为有些关于Jersey与Hk2绑定的传闻,并且难以与其他JSR-330实现共存。
public class Foo { @Inject private String field; }我有一半期望发生一些魔法,因此@Inject注释导致一个setter变得可用,但事实并非如此:
Foo foo = new Foo(); foo.setField("Bar"); // method setField(String) is undefined for the type Foo 如何在不调用框架的情况下(方便地)测试这种带注释的类? 如果做不到这一点,我怎么能以可移植的方式调用框架(即没有将我的测试代码紧密耦合到Hk2,Guice等) 如果做不到这一点,以这种方式测试类的典型,干净的方法是什么?I have previously used Spring DI, and one of the benefits I perceive is that I can test my Spring bean classes without involving Spring (imports omitted for brevity):
public class Foo { private String field; public void setField(String field) { this.field = field; } public String getField() { return field; } } public class TestFoo { @Test public void test_field_is_set() { Foo foo = new Foo(); foo.setField("Bar"); assertEquals("Bar", foo.getField()); } }Now I am experimenting with JSR-330, which means not explicitly writing setters.
I'm using Hk2 so far, purely because of some anecdotal stuff about Jersey being tied to Hk2, and making it difficult to co-habit with other JSR-330 implementations.
public class Foo { @Inject private String field; }I half expected some magic to happen, whereby the @Inject annotation caused a setter to become available, but this is not the case:
Foo foo = new Foo(); foo.setField("Bar"); // method setField(String) is undefined for the type Foo How can I (conveniently) test this kind of annotated class without invoking a framework? Failing that, how can I invoke a framework in a portable way (i.e. without tightly coupling my test code to Hk2, Guice, etc.) Failing that, what's a typical, clean way to test classes annotated in this way?最满意答案
最简单的方法是使字段package-private(而不是private),然后在测试中直接设置它们。 (如果测试在同一个包中,则有效)
public class Foo { @Inject String field; } Foo foo = new Foo(); foo.field = "bar";这具有避免反射的优点,因此可以安全地进行重构。
It turns out that frameworks relying on private/protected field access are not so uncommon. Hibernate, JPA, several JSR-330 implementations, including Spring itself, all do it.
Spring's spring-test package provides a ReflectionTestUtils class containing static methods for accessing these fields.
Using this one can test the class in the question thus:
import static org.springframework.test.util.ReflectionTestUtils.*; ... @Test public void testUsingSpringReflectionTestUtils() { Foo foo = new Foo(); setField(foo, "field", "Bar"); assertEquals("Bar", foo.getField()); }You need spring-test and spring-core in your test classpath for this to work, but it doesn't add a dependency on Spring for your production code.
(Comments welcome about alternative implementations of the same principle welcome. I don't think it's worth rolling one's own, however simple it would be, given that Spring has a good implementation.)
更多推荐
发布评论