简体   繁体   中英

JUnit how to test multiple functions

My question is: if I have a method to test, let's say a constructor for an object representing a person: public void Person(String name){this.name = name;} , is it silly to create one test case like:

public class PersonTest {

@Test
public void testPerson() throws myException{
    // First thing I want to test
    try {
        new Person("name to looooooooooooooong");
        fail("This test was supposed to throw an exception: name too long");
    } catch (Exception e) {
        if (e instanceof myException)
            assertEquals("MSG: name not valid!", "Name not valid", e.getMessage());
    }
    //Second thing I want to test
    try {
        new Person("name to short");
        fail("This test was supposed to throw an exception: name too short");
    } catch (Exception e) {
        if (e instanceof myException)
            assertEquals("MSG: name not valid!", "Name not valid", e.getMessage());
    }
    //Oter things I want to test ...
}

Or should I create one test suit for each object and one test case for each method to be testes? But what if I want to test several parameters for a method? should I write a test case for each case? Like:

  • one test case for a name too long
  • one test case for name too short
  • one test case for name containing numbers and so on ?

Regarding, the constructor.. if there is a chance that an exception can be thrown based on the input then testing for that is all fine.

In general if there is any logic that consider important then you should opt for unit testing those parts of code. You have to be smart though no to test too much as after some point if you get over 60/70% of coverage, meaning you have tested the most important logic, you will get to the point of dimminishing returns as testing more would mean more a waste of time than the actual benefit.

Regarding the approach of :

one test case for a name too long

one test case for name too short one

test case for name containing numbers and so on ?

That sounds good as you want your tests to cover one logical path in your method.. and ideally no more. If you do start testing more stuff then you will end up will a lot of bloated test cases which would be hard to debug, understand and maintain.

Small classes with one / two public methods, and a suite of specialized test would be ideal.

One more thing to keep in mind is for each test case try to parameterize it if possible so that you would squeeze as many possibilities as possible for each of those tests.

I strongly suggest using project like : Junit Data Provider to write your parameterized cases. I have been using it for few years now and it makes things much easier than the built it junit parameterization (if you actually say there is any).

There is a nice tooling for testing exceptions in JUnit:

 @Rule
 public ExpectedException thrown= ExpectedException.none();

 @Test
 public void throwsExceptionWithSpecificType() {
     thrown.expect(myException.class);
     thrown.expectMessage("Name not valid");
     new Person("name to looooooooooooooong");
 }

The test for the "big" method will look like integration test where the smaller methods can be mocked.

If you can separate the "big" method into five isolated methods, then the "big" method could be further partitioned into semantically-/contextually-meaningful groups of the isolated methods.

Then you can mock the larger groupings of isolated methods for the "big" method.

Its perfect case for paramtererization. Create one test and pass all conditions as parameter object.

Refer : https://github.com/junit-team/junit4/wiki/parameterized-tests

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM