【问题标题】:Wicket Ajax test resetting DropDownChoice to nullWicket Ajax 测试将 DropDownChoice 重置为 null
【发布时间】:2020-07-23 18:21:26
【问题描述】:

我正在尝试为已添加到 DropDownChoice 组件的 Ajax 行为设置单元测试。当我调用 tester.executeAjaxEvent(...) 时,DropDownChoice 模型值被重置为“null”。我不了解 ajax 如何在检票口中工作的基本知识。有人可以帮我吗?为什么会触发“更改”事件,导致组件将其模型设置为空。

DropDownPage.html

<?xml version="1.0" encoding="UTF-8"?>
<html>
    <head>
        <title>DropDownPage</title>
    </head>
    <body>
        <form wicket:id="form">
            <select wicket:id="dropDown">
                <option>Option 1</option>
            </select>
        </form>
    </body>
</html>

DropDownPage.java

public class DropDownPage extends WebPage {
    private static final Logger log = LogManager.getLogger(DropDownPage.class);

    public DropDownPage() {
        Form<Void> form = new Form<Void>("form");
        add(form);
        
        DropDownChoice<String> dropDown = new DropDownChoice<String>("dropDown", new Model<String>(new String()), Arrays.asList(new String[] { "A", "B" }));
        dropDown.setOutputMarkupId(true);

        dropDown.add(new AjaxFormComponentUpdatingBehavior("change") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                String choice = dropDown.getModelObject();
                if (choice == null) {
                    nullCall(target);
                    return;
                }
                
                switch (choice) {
                case "A":
                    doAStuff(target);
                    break;
                case "B":
                    doBStuff(target);
                    break;
                default:
                    unknownType(target);
                }
            }
    });
        form.add(dropDown);
    }

    protected void doAStuff(AjaxRequestTarget target) {
        log.info("doAStuff(...)");
    }

    protected void doBStuff(AjaxRequestTarget target) {
        log.info("doBStuff(...)");
    }
    
    protected void nullCall(AjaxRequestTarget target) {
        log.info("nullCall(...)");
    }
    
    protected void unknownType(AjaxRequestTarget target) {
        log.info("unknownType(...)");
    }
}

TestDropDownAjax.java

public class TestDropDownAjax {
    private WicketTester tester;
    
    @Before
    public void setup() throws Exception {
        tester = new WicketTester();
    }
    
    @After
    public void tearDown() {
        tester.destroy();
    }
    
    int aCount = 0;
    int nullCount = 0;
    
    @SuppressWarnings("unchecked")
    @Test
    public void testDropDownPage() {
        DropDownPage dropDownPage = new DropDownPage() {
            @Override
            protected void doAStuff(AjaxRequestTarget target) {
                super.doAStuff(target);
                ++aCount;
            }
            
            @Override
            protected void nullCall(AjaxRequestTarget target) {
                super.nullCall(target);
                ++nullCount;
            }
        };
        
        DropDownChoice<String> dropDown = (DropDownChoice<String>) dropDownPage.get("form:dropDown");
        assertNotNull(dropDown);
        
        List<String> choices = (List<String>) dropDown.getChoices();
        String choice = choices.get(0);
        
        dropDown.setModelObject(choice);
        
        tester.startPage(dropDownPage);
        
        tester.assertModelValue("form:dropDown", dropDown.getModelObject());
        
        assertEquals(choice, dropDown.getModelObject());

        assertEquals(0, nullCount);
        assertEquals(0, aCount);
        
        tester.executeAjaxEvent("form:dropDown", "change");
        
        assertEquals(0, nullCount);     // fails here
        assertEquals(1, aCount);
    }
}

【问题讨论】:

    标签: java unit-testing junit4 wicket


    【解决方案1】:

    AjaxFormComponentUpdatingBehavior 在调用 update 方法之前,会调用内部方法 inputChanged。此方法尝试将最新的用户输入转换为下拉模型的新值。由于您实际上并没有输入任何新内容,这将被解释为选择空选项,导致模型值变为null

    因此,您也需要通过 WicketTester 进行表单输入。

    一种方法是通过FormTester

    FormTester formTester = tester.newFormTester("form");
    formTester.select("dropDown", 0);
    tester.executeAjaxEvent("form:dropDown", "change");
    

    这将使您的测试通过。

    【讨论】:

    • Jeroen,帮我理解为什么我需要这样做。我在调用“dropDown.setModelObject(choice)”时更改了模型,但您说我“实际上没有输入任何新内容”。组件是否有一个变量是与模型对象不同的选定值?有一种直接操作这个变量而不是改变组件的选定值的方法?我可以得到它的值吗?
    • 最好查看AjaxFormComponentUpdatingBehavior 的来源以了解究竟发生了什么,但本质上:当change 事件触发时,表单将查看请求参数(或者查询或 POST 参数)用于新输入。我不确定是否有办法直接从 WicketTester 操作这些
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多