为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

森栏 2022-09-22 15:50:38

我有一个自动连线变量


@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


查看完整描述

3 回答

?
长风秋雁

TA贡献1475条经验 获得超7个赞

您可以在每次测试之前创建它。像


private DocumentConfig documentConfig;


@Before

public void createConfig() {

    documentConfig = new DocumentConfig(mockedParams);

}


查看完整回答
反对 回复 2022-09-22
?
Cats萌萌

TA贡献1492条经验 获得超9个赞

一种常用的方法是设置一个虚拟用户并将其注入到方法中(用 注释),以便在每个测试中重置整个上下文,例如:DocumentConfigsetUp()@Before


@Before

public void setUp() {

    this.documentConfig = new DocumentConfig();

    this.documentConfig.setNameRequired(false);

    this.service = new DocumentService(this.documentConfig);

}

在本例中,我设置了一个带有 be 的简单对象。我可能会删除该语句,因为无论如何都会默认为。nameRequiredfalsebooleanfalse


如果不使用构造函数注入,并且没有 的 setter,则必须使用反射来注入字段,例如:documentConfig


ReflectionTestUtils.setField(this.service, "documentConfig", this.documentConfig);

在你的测试中,你现在可以写这样的东西:


@Test

public void save_failure() {

    this.documentConfig.setNameRequired(true);

    // TODO: Implement test

}

或者,您可以模拟 ,这样您就不依赖于其实现来测试 。我假设您正在调用 代码中的某个位置,因此您可以像这样模拟它:DocumentConfigDocumentServiceisNameRequired()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

    }

}


查看完整回答
反对 回复 2022-09-22
?
哈士奇WWW

TA贡献1477条经验 获得超6个赞

目前尚不清楚您使用的测试框架。对于普通单元测试,使值可通过 setter 或构造函数注入来注入。任何最适合您的特定情况的东西。

如果要注入大量(超过三个 ;-) 此类值,则可以考虑引入一个配置类,将所有这些值作为单个参数注入。


查看完整回答
反对 回复 2022-09-22

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信