spring 3自动assembly和junittesting

我的代码:

@Component public class A { @Autowired private B b; public void method() {} } public interface X {...} @Component public class B implements X { ... } 

我想单独testingA级。我是否必须模拟B级? 如果是的话,怎么样? 因为它是自动assembly的,并且没有可以发送嘲弄对象的setter。

我想单独testingA级

你应该绝对模仿B,而不是实例化和注入一个B的实例。关键是要testingA是否工作,所以你不应该让一个潜在的破坏B干扰testingA.

这就是说,我强烈推荐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 } 

下面是我如何使用Spring 3.1,JUnit 4.7和Mockito 1.9进行testing的一个例子:

FooService.java

 public class FooService { @Autowired private FooDAO fooDAO; public Foo find(Long id) { return fooDAO.findById(id); } } 

FooDAO.java

 public class FooDAO { public Foo findById(Long id) { /* implementation */ } } 

FooServiceTest.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); } } 

你可以使用Spring的ReflectionTestUtils.setField (或者junit扩展PrivateAccessor )通过reflection来注入字段,或者你可以创build一个模拟应用上下文并加载它。 虽然对于一个简单的单元(非集成)testing,但为了简单起见,我倾向于使用reflection。

这个论坛讨论对我有意义。 你可以将你的私有成员b声明为一个由B类实现的InterfaceBtypes(即:面向服务),然后声明一个MockB类也将实现相同的接口。 在您的testing环境应用程序上下文中,声明MockB类和您的生产应用程序上下文,您声明了正常的B类,在任何情况下,A类的代码都不需要更改,因为它将自动连线。