如何编写非封装的单元测试?

我有一个自动连线变量


@Autowired

private DocumentConfig documentConfig;

我想使用此配置对象的各种状态对文档服务进行测试。我有哪些选择?什么是最好的选择?


第一个想法是这样的:


@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


森栏
浏览 179回答 3
3回答

长风秋雁

您可以在每次测试之前创建它。像private DocumentConfig documentConfig;@Beforepublic void createConfig() {    documentConfig = new DocumentConfig(mockedParams);}

Cats萌萌

一种常用的方法是设置一个虚拟用户并将其注入到方法中(用 注释),以便在每个测试中重置整个上下文,例如:DocumentConfigsetUp()@Before@Beforepublic void setUp() {    this.documentConfig = new DocumentConfig();    this.documentConfig.setNameRequired(false);    this.service = new DocumentService(this.documentConfig);}在本例中,我设置了一个带有 be 的简单对象。我可能会删除该语句,因为无论如何都会默认为。nameRequiredfalsebooleanfalse如果不使用构造函数注入,并且没有 的 setter,则必须使用反射来注入字段,例如:documentConfigReflectionTestUtils.setField(this.service, "documentConfig", this.documentConfig);在你的测试中,你现在可以写这样的东西:@Testpublic void save_failure() {    this.documentConfig.setNameRequired(true);    // TODO: Implement test}或者,您可以模拟 ,这样您就不依赖于其实现来测试 。我假设您正在调用 代码中的某个位置,因此您可以像这样模拟它:DocumentConfigDocumentServiceisNameRequired()DocumentService@Beforepublic void setUp() {    // Use a static import for Mockito.mock()    this.documentConfig = mock(DocumentConfig.class);    this.service = new DocumentService(this.documentConfig);}@Testpublic 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    }}

哈士奇WWW

目前尚不清楚您使用的测试框架。对于普通单元测试,使值可通过 setter 或构造函数注入来注入。任何最适合您的特定情况的东西。如果要注入大量(超过三个 ;-) 此类值,则可以考虑引入一个配置类,将所有这些值作为单个参数注入。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java