【问题标题】:How to create a Form<T> for a play (java) unit test now that Form.form() is deprecated?既然 Form.form() 已被弃用,如何为 play (java) 单元测试创​​建 Form<T>?
【发布时间】:2017-09-18 15:11:10
【问题描述】:

在处理表单的应用程序代码中,建议使用 FormFactory 围绕类型 T 的表单创建 Form 包装器。但是在测试时,创建 Form 的方法是什么? (测试中一定要注入FormFactory吗?)

我的应用做了类似的事情:

class MyAmazingClass {
    private final FormFactory formFactory;

    @Inject
    MyAmazingClass(FormFactory formFactory) {
        this.formFactory = formFactory;
    }

    public CompletionStage<Result> myAmazingMethodHandlingForms() {
        Form<String> form = formFactory.form(String.class).bindFromRequest();
        // ... Actually doing something
        return null;
    }
}

我的测试类(用于单元测试)应该是什么样的?

我正在尝试这样的事情,但我认为我不应该尝试注入 FormFactory(它似乎也不起作用):

public class MyAmazingClassTest extends WithApplication {

    @Mock
    FormFactory mockedFormFactory;

    @Inject
    FormFactory realFormFactory;

    MyAmazingClass myAmazingClass;

    @Override
    protected Application provideApplication() {
        return new GuiceApplicationBuilder().build();
    }

    @Before
    public void setUp() throws Exception {
        myAmazingClass = new MyAmazingClass(mockedFormFactory);
    }

    @Test
    public void testMyAmazingMethodHandlingForms() throws Exception {
        String myString = "ciao";
        Form<String> stringForm = realFormFactory.form(String.class).fill(myString);
        when(mockedFormFactory.form(eq(String.class)).bindFromRequest()).thenReturn(stringForm);
        myAmazingClass.myAmazingMethodHandlingForms();
        // Some assertions...
    }
}

我正在使用 JUnit 4、Java 8 和 Play 框架 2.5。

【问题讨论】:

    标签: java unit-testing playframework junit4 playframework-2.5


    【解决方案1】:

    我会说将模拟与实际应用程序混合并不是最好的主意。您应该使用模拟(并避免使用WithApplication),或者您可以通过调用app.injector().instanceOf()(包括您的MyAmazingClass)来使用“真实”实例。例如,仅使用模拟时:

    public class MyAmazingClassTest {
    
        @Test
        public void testMyAmazingMethodHandlingForms() throws Exception {
            Form<String> form = mock(Form.class);
            // setup the mocked form as you expect it to behave
    
            FormFactory formFactory = mock(FormFactory.class);
            when(formFactory.form(eq(String.class)).bindFromRequest()).thenReturn(form);
    
            MyAmazingClass myAmazingClass = new MyAmazingClass(formFactory);
            myAmazingClass.myAmazingMethodHandlingForms();
    
            // Some assertions...
        }
    }
    

    使用真实实例进行测试需要您发出请求,因为显然,您是从请求中绑定的:

    public class MyAmazingClassTest extends WithApplication {
    
        @Test
        public void testMyAmazingMethodHandlingForms() throws Exception {
            Map<String, String> formData = new HashMap<>();
            formData.put("some", "value");
            // fill the form with the test data
            Http.RequestBuilder fakeRequest = Helpers.fakeRequest().bodyForm(formData).method(Helpers.POST);
    
            Result result = Helpers.route(app, fakeRequest);
    
            // make assertions over the result or something else.
        }
    }
    

    【讨论】:

    • 感谢这个不错的答案,我喜欢你介绍加载“真实”实例的可能性(因为我还想稍后进行集成测试),这将非常有用。但是,你为什么告诉我我不应该扩展 WithApplication?如果应用程序没有启动,我应该如何运行测试? (java.lang.RuntimeException:没有启动的应用程序)我认为扩展 WithApplication 并提供 GuiceApplicationBuilder.build() 或 Helpers.fakeapplication() 是这样做的方法。
    • 然后您可以接受作为答案。所以这个问题不会出现在“未回答”过滤器中。
    • 抱歉,我还在编辑评论(你回复太快了!)因为我不知道回车键会为我添加评论。请再看一遍。
    • 如果您使用模拟,则不需要正在运行的应用程序。整个想法是孤立地测试组件。所以,如果MyAmazingClass 需要访问应用程序,你也需要模拟它。第二个示例扩展了 WithApplication,因为现在我们使用的是真正的组件。
    • 模拟MyAmazingClass 需要的任何东西。看起来它只需要`FormFactory,这样就足够了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多