我正在为一个标有@Autowired的几个字段的类编写一个单元测试。鉴于Spring正在自动解析这些字段的具体实现,我很难弄清楚如何在测试运行期间插入我的Mock对象(通过EasyMock创建)作为依赖项。在课堂上使用@Autowired意味着在该课程中缺少setter。有没有办法让我插入我的模拟对象而不在课堂上创建额外的setter?
这是我想要完成的一个例子:
public class SomeClassUnderTest implements SomeOtherClass{
@Autowired
private SomeType someType;
@Autowired
private SomeOtherType someOtherType;
@Override
public SomeReturnType someMethodIWouldLikeToTest(){
//Uses someType and someOtherType and returns SomeReturnType
}
}
以下是我在碰壁前制作Test类的方法:
public class MyTestClassForSomeClassUnderTest{
private SomeType someType;
private SomeOtherType someOtherType;
@Before
public void testSetUp(){
SomeClassUnderTest someClassToTest = new SomeClassUnderTest();
someType = EasyMock.createMock(SomeType.class);
someOtherType = EasyMock.createMock(SomeOtherType.class);
//How to set dependencies????
}
@Test
public void TestSomeMethodIWouldLikeToTest(){
//??????
}
}
向正确的方向努力将会很棒。
由于
答案 0 :(得分:34)
您可以使用ReflectionTestUtils
反射性地将依赖项直接注入字段,例如
ReflectionTestUtils.setField( testInstance, "fieldName", fieldValue );
有些人会争辩说,无论如何最好将类包装可见的setter方法添加到类中,仅由测试使用。或者,使用自动装配的构造函数而不是自动装配的字段,并将测试依赖项注入其中。
答案 1 :(得分:6)
虽然可以通过反射设置这些字段,但这样做会阻止您的开发工具查找这些字段的用法,并使您以后更难以重构SomeClassToTest
。
最好为这些字段添加公共设置器,并将@Autowired
注释放在这些字段上。这不仅避免了反射,而且还阐明了类的外部接口,并确保您的单元测试仅使用此接口。我看到SomeClassToTest
已经实现了SomeOtherClass
接口,我假设SomeClassToTest
的客户端只使用这个接口,所以在SomeClassToTest
公共上设置setter几乎没有危险
更好的是,使用构造函数注入并使字段最终。您仍然可以在构造函数参数上使用@Autowired
。
答案 2 :(得分:2)
我不推荐已被接受的答案,即自己使用反射(没有模拟框架)。
从EasyMock的3.2版开始,您可以使用注释来定义模拟并将它们注入到被测试的类中。有关如何操作的完整说明,请参阅EasyMock的官方文档: http://easymock.org/user-guide.html#mocking-annotations
以下是上述网站的一个例子:
import static org.easymock.EasyMock.*;
import org.easymock.EasyMockRunner;
import org.easymock.TestSubject;
import org.easymock.Mock;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(EasyMockRunner.class)
public class ExampleTest {
@TestSubject
private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2
@Mock
private Collaborator mock; // 1
@Test
public void testRemoveNonExistingDocument() {
replay(mock);
classUnderTest.removeDocument("Does not exist");
}
}