2

Chapter 02 of Spring in Action, Pg. 40 Using Spring Tool Suite, I've made the following:

MediaPlayer Interface

package com.spring.soundsystem;

public interface MediaPlayer {
    void play();
}

CompactDisc Interface

package com.spring.soundsystem;

public interface CompactDisc {
    void play();
}

CDPlayer Class Implements MediaPlayer

package com.spring.soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc cd;

    @Autowired
    public CDPlayer(CompactDisc cd) {
        this.cd = cd;
    }


    public void play() {
        cd.play();
    }

}

SgtPeppers Class Implements CompactDisc

package com.spring.soundsystem;

import org.springframework.stereotype.Component;

@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {

    private String title = "Sgt. Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";

    public void play() {
        System.out.println("Playing " + title + " by " + artist);

    }

}

CDPlayerConfig

package com.spring.soundsystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan()
public class CDPlayerConfig {}

CDPlayerTest

package com.spring.soundsystem;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {

    // public final StandardOutputStreamLog log = new StandardOutputStreamLog(); deprecated code in book replace with below
    @Rule
    public final SystemOutRule log = new SystemOutRule().enableLog();

    @Autowired
    private MediaPlayer player;

    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd);
    }

    @Test
    public void play() {
        log.clearLog(); // clears debug that occurred for some reason in log output
        player.play();
        assertEquals(
                "Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles",
                log.getLog());
    }

}

The trouble is, when I run the JUnit test there is a failure with the following trace:

org.junit.ComparisonFailure: expected:<... Band by The Beatles[]> but was:<... Band by The Beatles[
]>
    at org.junit.Assert.assertEquals(Assert.java:115)
    at org.junit.Assert.assertEquals(Assert.java:144)
    at com.spring.soundsystem.CDPlayerTest.play(CDPlayerTest.java:36)
...

The test should pass according to the text displayed but I am thinking that maybe this is a data type/memory comparison issue outside of the realm of my understanding? I don't see any unnecessary spaces or characters out of place so it must be something I simply cannot see without understanding the fundamentals of how this logging comparison works.

I also have an additional question, if anyone is willing, to please explain what all of this means from a 40k foot viewpoint. I am still trying to wrap my head around DI and the purpose behind what Spring is doing as far as wiring these classes together.

4 Answers4

5

I assume System.out.println is adding a newline to the end of your log message. That's why your assertion fails. I think changing it to this, will do the trick:

final String newLine = System.lineSeparator();
assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles"
    + newLine, log.getLog());
dpr
  • 10,591
  • 3
  • 41
  • 71
  • I did try that, but to no avail. New stack trace after adding a newline as suggested reads: org.junit.ComparisonFailure: expected:<... Band by The Beatles[] > but was:<... Band by The Beatles[ ] > What do the brackets mean at the end of Beatles? – Alex Ramsey Aug 15 '17 at 15:33
  • Did you try `\r\n` as well? println seems to be using the OS newline character. – dpr Aug 15 '17 at 15:38
  • That worked https://stackoverflow.com/questions/9260126/what-are-the-differences-between-char-literals-n-and-r-in-java – Alex Ramsey Aug 15 '17 at 17:20
  • @arr I slightly adapted the example to be OS independent by using the system property `line.separator` otherwise your test would have failed, if executed on linux or macOS. – dpr Aug 15 '17 at 17:49
1
@Test
    public void play() {
        log.clearLog();
        player.play();
        assertEquals(
                "Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n",
                log.getLogWithNormalizedLineSeparator());
    }

//it works!
Name Surname
  • 359
  • 2
  • 2
1

If you debug the application, the assertEquals method compares two Object the first is the expected one (entered by you) and the second is the one that receives from the getLog () method, when verifying that String gets from the getLog () you will see that it additionally includes The log that Spring is launching on the console, is why it gives error and indicates that both objects are different.

0

Seems this issue was prevalent enough to mention in the docs for SystemOutRule.

Might be easiest to use something like this:
assertEquals("some text\n", systemOutRule.getLogWithNormalizedLineSeparator());

hboylan
  • 357
  • 3
  • 12