我的代码:
@Component
public class A {
@Autowired
private B b;
public void method() {}
}
public interface X {...}
@Component
public class B implements X {
...
}
我想在隔离类A中测试。我是否必须模拟B类?如果有,怎么样?因为它是自动装配的,并且没有可以发送模拟对象的setter。
答案 0 :(得分:83)
我想在隔离级别A中进行测试。
你应该绝对模拟B,而不是实例化并注入B的实例。重点是测试A是否有效,所以你不应该允许潜在破坏的B干扰A的测试。
那就是说,我强烈推荐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
}
答案 1 :(得分:18)
以下是我使用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
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);
}
}
答案 2 :(得分:15)
您可以使用Spring的ReflectionTestUtils.setField
(或junit扩展PrivateAccessor
)通过反射注入字段,或者您可以创建模拟应用程序上下文并加载它。虽然对于一个简单的单元(非集成)测试,我赞成使用反射来简化。
答案 3 :(得分:0)
This forum discussion对我有意义。您可以将私有成员b声明为由B类实现的InterfaceB类型(即:面向服务),然后声明MockB类也将实现相同的接口。在您的测试环境应用程序上下文中,您声明MockB类和生产应用程序上下文,您声明了正常的B类,在任何一种情况下,A类的代码都不需要更改,因为它将自动连接。