Junit multiple results in one test

你离开我真会死。 提交于 2020-12-13 19:17:31

问题


Ok, I know this is considered an anti-pattern, and I am certainly open to a better way of doing this.

I have a map of enum values. I want to ensure that each of those enum values is assigned to something. My test looks like this.

@Test
public void eachRowRequiresCellCalc()
{
    Model model = new Model();
    EnumValues[] values = EnumValues.values();
    for (EnumValues value : values)
    {
        Assert.assertTrue(String.format("%s must be assigned", value.name()), model.hasEnumValue(value));
    }
}

This works and accomplishes 90% of what I'm looking for. What it doesn't do is show me if multiple enum values are unassigned (it fails on the first). Is there a way with JUnit to have multiple fails per test?


回答1:


Ideally you would not want to check for all values once you get a failure since it is anyways going to fail.

But a workaround I would suggest, but not sure if it works for you:

@Test
public void eachRowRequiresCellCalc()
{
    Model model = new Model();
    EnumValues[] values = EnumValues.values();
    List<EnumValues> isFalse = new ArrayList<EnumValues>;
    for (EnumValues value : values)
    {
        if(!model.hasEnumValue(value)) {
            isFalse.add(value);
        }
    }

    //Now you have the array of incorrect values in 'isFalse'
}



回答2:


You cannot have multiple fails per test. But you can do something similar by tracking the failures in the for loop. Then outside the for loop print out your string in a single assert.

@Test
public void eachRowRequiresCellCalc()
{
 Model model = new Model();
 EnumValues[] values = EnumValues.values();
 String errors = "";
 for (EnumValues value : values)
 {
    if(!model.hasEnumValue(value))
      errors += String.format("%s must be assigned", value.name()+". ");
 }
 if(!errors.isEmpty()){
    fail(errors);
 }
}



回答3:


A way to express this using junit-quickcheck would be:

@RunWith(Theories.class)
public class Models {
    @Theory public void mustHaveValue(@ForAll @ValuesOf EnumValues e) {
        assertTrue(e.name(), new Model().hasEnumValue(e));
    }
}

This would run the theory method for every value of your enum.

Another way to express this would be via a parameterized test.

(Full disclosure: I am the creator of junit-quickcheck.)




回答4:


I know you asked about JUnit, but if you are in a position to consider TestNG, you can define a method as @DataProvider, which will supply parameters to a @Test method. What you seem to be looking for fits this perfectly.

Another option that comes to mind is that you might want to look into MatcherAssert.assertThat with collections matchers. Also it has better logging for your asserts - you might not need to use string format.

A suggestion regarding unit tests, if you don't mind: If you brake down a test method into blocks of given - when - then parts, it greatly improves their readability. given sets up the test case (variables, mocks, etc), when executes the method that is being tested, then is the part where you check the result (assert, verify, ...). I have found that following this structure helps others as well as myself weeks after the test has been written to understand what is going on.




回答5:


I am aware this is an older question, but for anyone who stumbles upon it now, like I did - as of today, JUnit provides an assertAll() function, which can be used just for that, so there's no more need to fiddle around trying to get the results of multiple chained assertions :)

Here's the reference, hope this saves you some time! Would for sure have saved some of mine if I had known about it earlier.



来源:https://stackoverflow.com/questions/26366274/junit-multiple-results-in-one-test

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!