0

I have been using have for two years now and now I'm trying to learn TDD (Test-Driven Development) and JUnit, the FizzBuzz Kata looked like a good place to start. So I did it:

public class FizzBuzz {
    public static void main(String[] args) {
        Generator generator = new Generator();
        List<String> numbers = generator.fill(1, 100);
        numbers.forEach( item -> System.out.println(item) );
    }
}

It's works find by now I have a question regarding my GeneratorTest.java:

public class GeneratorTest {
@Test
public void checkFizz() {
    //Arrange
    Generator generator = new Generator(); // This line is on every test!

    //Act
    final int fizzNumber = 3;
    final int containsFizz = 13;

    final String result1 = generator.transform(fizzNumber);
    final String result2 = generator.transform(containsFizz);

    // Assert
    assertEquals("Fizz", result1);
    assertEquals("Fizz", result2);
}

@Test
public void checkBuzz() {
    //Arrange
    Generator generator = new Generator(); // This line is on every test!

    //Act
    final int buzzNumber = 5;
    final int containsBuzz = 52;

    final String result1 = generator.transform(buzzNumber);
    final String result2 = generator.transform(containsBuzz);

    // Assert
    assertEquals("Buzz", result1);
    assertEquals("Buzz", result2);
}

@Test
public void checkFizzBuzz() {
    //Arrange
    Generator generator = new Generator(); // This line is on every test!

    //Act
    final int fizzBuzzNumber = 15;
    final int containsFizzBuzz = 53;

    final String result1 = generator.transform(fizzBuzzNumber);
    final String result2 = generator.transform(containsFizzBuzz);

    // Assert
    assertEquals("FizzBuzz", result1);
    assertEquals("FizzBuzz", result2);
}

@Test
public void checkFillSize() {
    //Arrange
    Generator generator = new Generator(); // This line is on every test!

    //Act
    final int lowerBound = 2;
    final int upperBound = 100;
    final int expectedSize = upperBound - lowerBound + 1;
    List<String> filledList = generator.fill(lowerBound, upperBound);

    //Assert
    assertEquals(expectedSize, filledList.size() );
}

@Test
public void checkFillContents() {
    //Arrange
    Generator generator = new Generator(); // This line is on every test!

    //Act
    ArrayList<String> expectedList = new ArrayList<>( Arrays.asList("1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "Fizz", "14", "FizzBuzz", "16", "17", "Fizz", "19", "Buzz", "Fizz", "22", "Fizz", "Fizz", "Buzz", "26", "Fizz", "28", "29", "FizzBuzz") ) ;
    List<String> filledList = generator.fill(1, expectedList.size() );

    //Assert
    assertEquals(expectedList, filledList);
}

@Test
public void checkFillCrossedBounds() {
    //Arrange
    Generator generator = new Generator(); // This line is on every test!

    //Act
    final int lowerBound = 100;
    final int upperBound = 1;
    final int expectedSize = 0;
    List<String> filledList = generator.fill(lowerBound, upperBound);

    //Assert
    assertEquals(expectedSize, filledList.size() );
}

Is there a way to make a singleton generator? And if so, is it a good practice?

I thought of doing it in the constructor but, I'm not sure if is the "right" way because I'm fairly new to JUnit and TDD.

PS: Greetings from Spain!

jpuriol
  • 362
  • 2
  • 14
  • 2
    Why would you want a singleton? It seems to be a completely stateless object. Creating it each time you need one is thus perfectly fine. You can of course avoid creating it in each test method by creating it in the constructor, or in a `@Before`-annotated method. – JB Nizet Sep 20 '17 at 18:53
  • 1
    See https://stackoverflow.com/questions/20295578/difference-between-before-beforeclass-beforeeach-and-beforeall – PM 77-1 Sep 20 '17 at 18:54
  • Well "singleton" it just the name I used. Maybe is not appropriate for this case, you are right is a stateless object. What I don't like is the duplicated code. – jpuriol Sep 20 '17 at 18:58
  • Then use a setup method. That's what they're for. – JB Nizet Sep 20 '17 at 19:01

1 Answers1

3

I agree with JB Nizet, each tests are independent of each others.

So, your class Generator must not to be a singleton.
I don't know Java very well, but within each Test Runner you have some methods like :

  • BeforeEach
  • AfterEach
  • BeforeAll
  • AfterAll

For exemple your line Generator generator = new Generator(); can be :

public class GeneratorTest {
    private Generator generator = null

    @Before
    public void runBeforeEachMethod() {
       this.generator = new Generator();
    }

    // your tests
}

Therefore, for each test you have a new instance of Generator. You can use BeforeAll too, but changing the state of your generator may lead to some undesirable side effects making your test fail.

You can check out this documentation: https://www.mkyong.com/unittest/junit-4-tutorial-1-basic-usage/

Mik378
  • 21,881
  • 15
  • 82
  • 180
mickaelw
  • 1,453
  • 2
  • 11
  • 28
  • Or you could use directly the `GeneratorTest`'s constructor and mark your variable `generator` `final`. In this way with the keyword `final`, you highlight the fact that jUnit recreate a class instance for each test. – Mik378 Sep 23 '17 at 19:56
  • @Mik378 Using *final* for fields should be your preferred first choice for production code. For unit tests, the informal best practice is to have a non-final field and setup within a method annotated with @ Before. – GhostCat Sep 25 '17 at 08:14
  • @GhostCat Check out the book "Growing Object-oriented software, guided by Tests" by Steve Freeman, you will see that making variables `final` is a good practice too. – Mik378 Sep 25 '17 at 08:53