我有一个自动连接的变量
@Autowired
private DocumentConfig documentConfig;
我想使用此配置对象的各种状态对DocumentService进行测试。我有什么选择?最好的选择是什么?
第一个想法是:
@Test
public void save_failure() {
documentConfig.setNameRequired(true);
/*
testing code goes here
*/
documentConfig.setNameRequired(false);
}
但是我想更加确定在测试之后将变量重置为不干扰其他测试,以确保只有此测试才是导致问题的原因。
我的新主意是:
@Before
public void after() { documentConfig.setNameRequired(true); }
@Test
public void save_failure() {
/*
testing code goes here
*/
}
@After
public void after() { documentConfig.setNameRequired(false); }
但是,这根本不起作用,因为对整个文件而不是对单个测试执行“前后”操作。我不希望只为一个测试就创建一个新文件。
我现在已经达成妥协:
@Test
public void save_failure() {
documentConfig.setNameRequired(true);
/*
testing code goes here
*/
}
@After
public void after() { documentConfig.setNameRequired(false); }
似乎可以做我想做的所有事情,但是我有几个问题。
假设nameRequired
以false开头,是否保证不会干扰其他测试?
有什么办法可以使我更清楚吗?为了我自己和他人。
答案 0 :(得分:2)
您可以在每次测试之前创建它。有点像
private DocumentConfig documentConfig;
@Before
public void createConfig() {
documentConfig = new DocumentConfig(mockedParams);
}
答案 1 :(得分:1)
使用哪种测试框架尚不清楚。对于普通单元测试,请通过设置器或构造函数注入使该值可注入。无论哪种情况最适合您的具体情况。
如果要注入很多(超过三个;-),则可以考虑引入配置类以将所有这些值作为单个参数注入。
答案 2 :(得分:1)
一种常用的方法是设置一个虚拟DocumentConfig
并将其注入setUp()
方法(用@Before
注释)中,以便在每个测试中重置整个上下文,例如例如:
@Before
public void setUp() {
this.documentConfig = new DocumentConfig();
this.documentConfig.setNameRequired(false);
this.service = new DocumentService(this.documentConfig);
}
在这种情况下,我设置了一个简单的对象,其中nameRequired
为false
。我可能可以删除该语句,因为无论如何boolean
字段默认为false
。
如果不使用构造函数注入,并且没有documentConfig
的二传手,则必须使用反射来注入字段,例如:
ReflectionTestUtils.setField(this.service, "documentConfig", this.documentConfig);
在测试中,您现在可以编写如下内容:
@Test
public void save_failure() {
this.documentConfig.setNameRequired(true);
// TODO: Implement test
}
或者,您可以模拟DocumentConfig
,这样就不必依赖其实现来测试DocumentService
。我假设您正在isNameRequired()
的代码中的某个地方调用DocumentService
,因此可以这样模拟它:
@Before
public void setUp() {
// Use a static import for Mockito.mock()
this.documentConfig = mock(DocumentConfig.class);
this.service = new DocumentService(this.documentConfig);
}
@Test
public void save_failure() {
// Use a static import for Mockito.when()
when(this.documentConfig.isNameRequired()).thenReturn(true);
// TODO: Implement test
}
由于这种模拟/注入设置经常发生,因此Mockito也拥有自己的运行程序,可让您摆脱setUp()
方法,例如:
@RunWith(MockitoJUnitRunner.class)
public class DocumentServiceTest {
@InjectMocks
private DocumentService documentService;
@Mock
private DocumentConfig documentConfig;
@Test
public void save_failure() {
when(this.documentConfig.isNameRequired()).thenReturn(true);
// TODO: Implement test
}
}