spring 3 自动装配和 junit 测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3660933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
spring 3 autowiring and junit testing
提问by mike27
My code:
我的代码:
@Component
public class A {
@Autowired
private B b;
public void method() {}
}
public interface X {...}
@Component
public class B implements X {
...
}
I want to test in isolation class A. Do I have to mock class B? If yes, how? Because it is autowired and there is no setter where i could send the mocked object.
我想在隔离类 A 中测试。我必须模拟 B 类吗?如果是,如何?因为它是自动装配的,并且没有可以发送模拟对象的设置器。
回答by earldouglas
I want to test in isolation class A.
我想在隔离级别 A 中进行测试。
You should absolutely mock B, rather than instantiate and inject an instance of B. The point is to test A whether or not B works, so you should not allow a potentially broken B interfere with the testing of A.
你应该完全模拟 B,而不是实例化和注入 B 的实例。重点是测试 A 是否 B 工作,所以你不应该让潜在的 B 干扰对 A 的测试。
That said, I highly recommend Mockito. As mocking frameworks go, it is extremely easy to use. You would write something like the following:
也就是说,我强烈推荐Mockito。随着模拟框架的发展,它非常易于使用。您将编写如下内容:
@Test
public void testA() {
A a = new A();
B b = Mockito.mock(B.class); // create a mock of B
Mockito.when(b.getMeaningOfLife()).thenReturn(42); // define mocked behavior of b
ReflectionTestUtils.setField(a, "b", b); // inject b into the B attribute of A
a.method();
// call whatever asserts you need here
}
回答by Mike Partridge
Here's an example of how I got my tests working with Spring 3.1, JUnit 4.7, and Mockito 1.9:
这是我如何使用 Spring 3.1、JUnit 4.7 和 Mockito 1.9 进行测试的示例:
FooService.java
服务类
public class FooService {
@Autowired private FooDAO fooDAO;
public Foo find(Long id) {
return fooDAO.findById(id);
}
}
FooDAO.java
FooDAO.java
public class FooDAO {
public Foo findById(Long id) {
/* implementation */
}
}
FooServiceTest.java
服务测试.java
@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
@Mock private FooDAO mockFooDAO;
@InjectMocks private FooService fooService = new FooService();
@Test public final void findAll() {
Foo foo = new Foo(1L);
when(mockFooDAO.findById(foo.getId()).thenReturn(foo);
Foo found = fooService.findById(foo.getId());
assertEquals(foo, found);
}
}
回答by Jeff Storey
You can inject the field via reflection using Spring's ReflectionTestUtils.setField(or the junit extension PrivateAccessor) or you can create a mock application context and load that. Though for a simple unit (non-integration) test, I favor using reflection for simplicity.
您可以使用 Spring 的ReflectionTestUtils.setField(或 junit 扩展PrivateAccessor)通过反射注入该字段,或者您可以创建一个模拟应用程序上下文并加载它。尽管对于一个简单的单元(非集成)测试,为了简单起见,我更喜欢使用反射。
回答by Aaron
This forum discussionmakes sense to me. You can declare your private member b as a type of InterfaceB which is implemented by the class B (ie: service-oriented) then declare a MockB class would also implement the same interface. In your test environment application context, you declare MockB class and your production application context you declare the normal B class and in either case, the code for class A does not need to be changed since it will be auto-wired.
这个论坛讨论对我来说很有意义。您可以将私有成员 b 声明为由类 B 实现的 InterfaceB 类型(即:面向服务),然后声明一个 MockB 类也将实现相同的接口。在您的测试环境应用程序上下文中,您声明 MockB 类,而您的生产应用程序上下文则声明普通 B 类,在任何一种情况下,A 类的代码都不需要更改,因为它将被自动连接。

