简体   繁体   中英

How to test a method that calls different methods inside?

I have a method to unit test called addSong(song,userId) in service class. I am calling three methods inside it from Dao class . I am using Easy mock to mock dao class . In the setup I first mock all the methods I am calling in addSong(song,userId) , and then calling the service.addsong(song,userId) method fot test.

But I am getting the following error:

Java.lang.IllegalStateException: missing behavior definition for the preceding method call:
MusicPlayerDao.addSong(song)
Usage is: expect(a.foo()).andXXX()
    at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:42)
    at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
    at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:97)
    at service.MusicPlayerDao$$EnhancerByCGLIB$$45bc3ca1.addSong(<generated>)
    at service.MusicPlayerServiceImpl.addSong(MusicPlayerServiceImpl.java:43)
    at AddSongTest.addSongs(AddSongTest.java:90)

Here is my code:

private void addSongSetup() throws SQLException{
    this.album = new Album();
    album.setAlbumName("album");
    this.genre = new Genre();
    genre.setGenreName("genre");
    this.song = new Song("song",this.album,3,"artist","composer",this.genre);
    EasyMock.expect(this.dao.addSong(song)).andReturn(1).anyTimes();
    EasyMock.expect(this.dao.addGenre(genre, 1)).andReturn(1).anyTimes();
    EasyMock.expect(this.dao.addAlbum(album, 1)).andReturn(1).anyTimes();
    EasyMock.expect(this.dao.userIdSongsMapping(1,1)).andReturn(1).anyTimes();
}

@Test
public void addSongs(){

    this.album = new Album();
    album.setAlbumName("album");
    this.genre = new Genre();
    genre.setGenreName("genre");
    this.song = new Song("song",this.album,3,"artist","composer",this.genre);
    try {
        System.out.println(this.dao.addSong(song));
        boolean status = this.service.addSong(song, 1);
        assertEquals(true,status);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

My addSong method in service class:

public boolean addSong(Song song, int userId) throws Exception {

    MusicPlayerDaoInterface musicPlayerDao = MusicPlayerDao.getInstance();
    boolean status = false;
    int songId = 0;

    TransactionManager transactionManager = TransactionManagerImpl
            .getInstance();
    try {
        if (song != null) {
            if (song.getTitle() != null) {
                transactionManager.begin();
                songId = musicPlayerDao.addSong(song);
                song.setSongId(songId);
                if (song.getGenre() != null
                        && song.getGenre().getGenreName() != null) {
                    musicPlayerDao.addGenre(song.getGenre(),
                            song.getSongId());
                }
                if (song.getAlbum() != null
                        && song.getAlbum().getAlbumName() != null) {
                    musicPlayerDao.addAlbum(song.getAlbum(),
                            song.getSongId());
                }
                if (userId != 0 && songId != 0) {
                    musicPlayerDao.userIdSongsMapping(userId,
                            song.getSongId());
                }
                transactionManager.commit();
                status = true;
            }
        }
    } catch (SQLException | RollbackException | HeuristicMixedException
            | HeuristicRollbackException e) {
        transactionManager.rollback();
        status = false;
        throw e;

    }

    return status;
}

I don't know were I am going wrong. Please help.

I think you are missing a EasyMock.replay statement after you record the expected behaviour. Something like

EasyMock.replay(this.dao);

From the EasyMock guide :

To get a Mock Object, we need to

  1. create a Mock Object for the interface we would like to simulate
  2. record the expected behavior
  3. switch the Mock Object to replay state

try removing the following lines from the addSongs test case:

this.album = new Album();
album.setAlbumName("album");
this.genre = new Genre();
genre.setGenreName("genre");
this.song = new Song("song",this.album,3,"artist","composer",this.genre);

I assume that addSongSetup is invoked before addSongs (eg; @Before ). You are reassigning values to your variables album, genre and song in addSong , which, I suppose, EasyMock cannot match to your mock setup in addSongSetup as (depending on how EasyMock implemented this)

  1. you forgot to implement hashcode or equals in Song, Album, Genre or,
  2. EasyMock uses Object identity (ie, reference comparison)

I guess it's 1.

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