Wicket Ajax 测试将 DropDownChoice 重置为 null

Wicket Ajax test resetting DropDownChoice to null

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

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);
    }
}

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

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

一种方法是通过 FormTester:

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

这将使您的测试通过。