Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
  1. Create a new test project in the FindHighestNumber solution

  2. We’ll draft out a test defining what we think we want the production code to do

  3. Code Block
    languagejava
    public class TopicScoreWriterTest
    {
       @Test[Test]
       public   void  verify_topic_score_details_written_out_once()
       {
          // arrange
          String physics = "Physics";
    
          ArrayList<TopicTopScore>TopicTopScore[] topTopScores = new ArrayList<>();
          topTopScores.add({ new TopicTopScore(physics, 89)) };
          
           TopicScoreWriter cut = new TopicScoreWriter();
          
          // act
          cut.writeScores( topTopScores );
          
          // assert
       }
    }
  4. Line 10 represents the implementation class. We will call a method called writeScores() passing an array TopicTopScores. Since this method will not return a result that is testable in this context, how are we going to test the result of the writeScrores(), it's going to make a call to a Java API. We are not going to test the Java API call, many millions of developers have already done this. We can use the mocking libraries verify capability. But what are we going to verify?

  5. We’ll begin by decoupling the Java API call to write to the file stream from the TopicScorWriter. To do this could pass into the constructor a java.io.FileWriter object or something similar. But this would tie the production too tightly to java.io.FileWriter. Instead, let’s pass an object that encapsulates the file writer functionality. This object needs to support two capabilities 1) open a text file to write to, and 2) write the formatted string to the opened text file. With this design in mind, we can update our test and then dig a little deeper into the implementation code.

  6. Our updated test class now looks like this

  7. Code Block
    languagejava
    publicnamespace classTopicWriterTests
    TopicScoreWriterTest{
    {    interface IFileWriter
        {
            void  writeLineWriteLine( String lineToWrite );
        }
        public class  @TestTopicWriterTests
        {
            [Test]
          public  public void  verifyVerify_topic_score_details_written_out_once()
            {
                // arrange
                String physics = "Physics";
                String art = "Art";
                String compSci = "Comp Sci";
                String expectedResult = "Physics, 89";
           ArrayList<TopicTopScore> topTopScores = new ArrayList<>();
          topTopScores.add(  TopicTopScore[] topTopScores = { new TopicTopScore(physics, 89)) };
                IFileWriter  String fileToWritefileWriter = "testfile.txt";
    Substitute.For<IFileWriter>();
         IFileWriter fileWriter = mock(IFileWriter.class); 
                TopicScoreWriter cut = new TopicScoreWriter( fileWriter );
                
                // act
                cut.writeScoresWriteScores( topTopScores );
    
                // assert
               verify( fileWriter, times.Received(1)).writeLineWriteLine(expectedResult);
            }
        }
    }
  8. Notice the use of the interface at line 3. We then use this interface to create Mock object at line 2118. At line 29 wr 26 we are going to verify that the method writeLineWriteLine() is called once with a string formatted as shown at line 1516.

  9. Move the IFileWriter interfaces into its own the same file as TopicScoreWriter

  10. Code Block
    package com.s2s.demos.topicmanager;namespace TopicManagerService
    {
        public interface IFileWriter
        {
            void  writeLineWriteLine( Stringstring lineToWrite );
        }
  11. Let’s write the implementation code for TopicScoreWriter. We’ve used a canned result (line 20) to test our theory

  12. Code Block
    languagejava
    package com.s2s.demos.topicmanager;  import java.util.ArrayList;
    
    /**
     *
     * @author selvy
     */
    public class TopicScoreWriter
    { public class TopicScoreWriter
        {
            private IFileWriter itsFileWriterfileWriter;
    
            public TopicScoreWriter(IFileWriter fileWriter)
    )        {
                this.itsFileWriterfileWriter = fileWriter;
            }
    
            public void writeScoresWriteScores(ArrayList<TopicTopScore>TopicTopScore[] topTopScores)
            {
          itsFileWriter.writeLine      fileWriter.WriteLine("Physics, 89");
            }
        }
    }
  13. Run the test and it should pass

  14. We’ll now update writeScoresWriteScores() so that it writes the data being passed

  15. Code Block
    languagejava
            public void writeScoresWriteScores(ArrayList<TopicTopScore>TopicTopScore[] topTopScores)
            {
                if ( topTopScores.size()Length > 0)
         )       {
                    TopicTopScore tts = topTopScores.get([0);];
                    Stringstring dataToWrite = tts.getTopicName()TopicName + ", " + tts.getTopScore();TopScore;
                    itsFileWriterfileWriter.writeLineWriteLine(dataToWrite);
                }
            }

  16. The if statement introduces a new logic path in the code, we should have test for this

  17. Code Block
    languagejava
         @Test   [Test]
          public  public void  verifyVerify_empty_array_topic_score_details_not_written()
            {
                // arrange
                String physics = "Physics";
                String art = "Art";
                String compSci = "Comp Sci";
                String expectedResult = "Physics, 89";
                ArrayList<TopicTopScore>TopicTopScore[] topTopScores = new ArrayList<>Array.Empty<TopicTopScore>();
    
                IFileWriter fileWriter = mock(IFileWriter.classSubstitute.For<IFileWriter>();
    
                TopicScoreWriter cut = new TopicScoreWriter( fileWriter );
                 // act
                cut.writeScoresWriteScores( topTopScores );
    
                // assert
              verify(  fileWriter, times(0).DidNotReceive().writeLine(Mockito.any())WriteLine(expectedResult);
            }
  18. Finally, add another test that writes more top scores for different topics

  19. Code Block
        @Test    [Test]
          public  public void  verifyVerify_topic_score_details_written_out_multiple_times()
            {
                // arrange
          String      string physics = "Physics";
                Stringstring art = "Art";
          String      string compSci = "Comp Sci";
          String      string physicsResult = "Physics, 89";
           String     string artsResult = "Art, 87";
          String      string comSciResult = "Comp Sci, 97";
    
            ArrayList<TopicTopScore>    TopicTopScore[] topTopScores = { new ArrayList<>TopicTopScore();physics, 89),
                                     topTopScores.add( new TopicTopScore(physics, 89));        topTopScores.add( new TopicTopScore(art, 87));,
                                                topTopScores.add( new TopicTopScore(compSci, 97))};
    
                 String fileToWrite = "testfile.txt";
                IFileWriter fileWriter = mock(IFileWriter.classSubstitute.For<IFileWriter>();
          
                TopicScoreWriter cut = new TopicScoreWriter( fileWriter );
    
                // act
                cut.writeScoresWriteScores( topTopScores );
    
                // assert
          verify(      fileWriter, times.Received(1)).writeLineWriteLine(physicsResult);
          verify(      fileWriter, times.Received(1)).writeLineWriteLine(artsResult);
          verify(      fileWriter, times.Received(1)).writeLineWriteLine(comSciResult);
            }
  20. And the implementation code has been updated to

  21. Code Block
    namespace TopicManagerService
    {
        public interface IFileWriter
        {
            void WriteLine(string lineToWrite);
        }
    
        public class TopicScoreWriter
        {
            private IFileWriter itsFileWriterfileWriter;
    
            public TopicScoreWriter(IFileWriter fileWriter)
    )        {
                this.itsFileWriterfileWriter = fileWriter;
            }
    
            public void writeScoresWriteScores(ArrayList<TopicTopScore>TopicTopScore[] topTopScores)
            {
          for(      foreach( TopicTopScore tts :in topTopScores )
                {
             String       string dataToWrite = tts.getTopicName()TopicName + ", " + tts.getTopScore()TopScore;
             itsFileWriter.writeLine       fileWriter.WriteLine(dataToWrite);
                }
            }
        }
    }