0

I am testing a GWTP presenter using Jukito, and can't seem to get named bindings to work.

I want to be able to test the onReveal() of my login widget, so I need to provide a copy of my CurrentUserDto that is logged in, and one that isn't. This is what I'm trying to do:

@RunWith(JukitoRunner.class)
public class LoginWidgetPresenterTest
{
    public static class Module extends JukitoModule
    {
        @Override
        protected void configureTest()
        {
            bind(CurrentUserDto.class).annotatedWith(Names.named("loggedIn")).toProvider(LoggedInUserProvider.class);
            bind(CurrentUserDto.class).annotatedWith(Names.named("loggedOut")).toProvider(LoggedOutUserProvider.class);
            
            // these don't work either:
            // bindNamed(CurrentUserDto.class, "loggedIn").toProvider(LoggedInUserProvider.class);
            // bindNamed(CurrentUserDto.class, "loggedOut").toProvider(LoggedOutUserProvider.class);
        }
        
        public static class LoggedInUserProvider implements Provider<CurrentUserDto>
        {
            @Override
            public CurrentUserDto get()
            {
                CurrentUserDto currentUser = new CurrentUserDto(true, 100L); // isLoggedIn, userId
                currentUser.setEmail("john@example.com");
                currentUser.setNickname("john");
                currentUser.setLogoutUrl("#logout");
                
                return currentUser;
            }
        }
        
        public static class LoggedOutUserProvider implements Provider<CurrentUserDto>
        {
            @Override
            public CurrentUserDto get()
            {
                CurrentUserDto currentUser = new CurrentUserDto(false, null); // isLoggedIn, userId
                
                return currentUser;
            }
        }
        
    }
    
    @Inject
    LoginWidgetPresenter presenter;
    
    @Test
    public void testLoggedInUser(LoginWidgetPresenter.MyView myView, @Named("loggedIn") CurrentUserDto currentUser)
    {
        // when
        presenter.onReveal();
        
        // then
        verify(myView).displayEmail(currentUser.getEmail());
        verify(myView).displayLogoutLink(currentUser.getLogoutUrl());
        
    }
    
    @Test
    public void testLoggedOutUser(LoginWidgetPresenter.MyView myView, @Named("loggedOut") CurrentUserDto currentUser)
    {
        // when
        presenter.onReveal();
        
        // then
        verify(myView, never()).displayEmail(currentUser.getEmail());
        verify(myView, never()).displayLogoutLink(currentUser.getLogoutUrl());
        
    }
    
}

I suspect it may be to do with the scopes, but I'm new to dependency injection so still getting my head around it.

When I only had one provider it worked fine, now I am using @Named the CurrentUserDto objects in the LoginWidgetPresenter are always null.

rusheb
  • 1,004
  • 9
  • 15
slugmandrew
  • 1,776
  • 2
  • 25
  • 45

2 Answers2

1

The following should work, as Jukito supports @Provides :

public static class Module extends JukitoModule
{
        @Override
        protected void configureTest()
        {
        }

        @Provides
        @Named("loggedIn")
        CurrentUserDto getLoggedInDto()
        {
            CurrentUserDto currentUser = new CurrentUserDto(true, 100L); // isLoggedIn, userId
            currentUser.setEmail("john@example.com");
            currentUser.setNickname("john");
            currentUser.setLogoutUrl("#logout");

            return currentUser;
        }

        @Provides
        @Named("loggedOut")
        CurrentUserDto getLoggedOutDto()
        {
            CurrentUserDto currentUser = new CurrentUserDto(false, null); // isLoggedIn, userId

            return currentUser;
        }
}
rusheb
  • 1,004
  • 9
  • 15
meriouma
  • 121
  • 5
  • The objects are still null when using the @Provides? – meriouma Jun 10 '14 at 18:04
  • 1
    Ah I get it now. I can't comment on the other answer, but your problem is indeed that the CurrentUserDto injected into LoginWidgetPresenter isn't the same as in your test. You need to bind CurrentUserDto (or your provider) into TestSingleton scope – meriouma Jun 10 '14 at 18:10
  • Thank you! Once I set the scope it meant I could inject the logged in one, call `setIsLoggedIn(false)` and then verify that the methods were never called. Cheers! – slugmandrew Jun 11 '14 at 08:24
0

I assume LoginWidgetPresenter has a bare CurrentUserDto injected. The parameter to your test method doesn't change the dependencies of the LoginWidgetPresenter. To handle this, you could have two different modules, each binding CurrentUserDto to a different Provider.

Tavian Barnes
  • 12,477
  • 4
  • 45
  • 118
  • `LoginWidgetPresenter` has a populated `CurrentUserDto` injected by a more complex Guice Provider (similar to this: https://github.com/ArcBees/ArcBees-tools/blob/master/archetypes/gwtp-appengine-objectify/src/main/java/com/arcbees/project/server/authentication/CurrentUserDtoProvider.java) - it checks whether the user is logged in to the appengine userservice and either returns the information of the logged in user, or information that no user is logged in. I thought that binding a different `Provider` in the `JukitoModule` would inject that instance into the `LoginWidgetPresenter` in the test. – slugmandrew Jun 10 '14 at 08:46
  • 1
    "I thought that binding a different Provider in the JukitoModule would inject that instance into the LoginWidgetPresenter in the test." It will, but `@Named("loggedIn") CurrentUserDto` is simply a different dependency than a bare `CurrentUserDto`. – Tavian Barnes Jun 10 '14 at 15:28
  • Sorry, I see what you mean by "bare" now - not annotated with `@Named` (doh!). I think I understand, so is there any way I can test the `onReveal()` method using two separate instances of `CurrentUserDto` in the same test case? – slugmandrew Jun 10 '14 at 16:11
  • I can't just do `currentUser.setIsLoggedIn(false)` because the one injected into the presenter is still set to logged in. – slugmandrew Jun 10 '14 at 16:12
  • I selected this as the right answer as it helped me realise that a `@Named` binding in my `JukitoModule` would not inject that instance into the `LoginWidgerPresenter` unless it was also annotated in the same way. – slugmandrew Jun 11 '14 at 08:32
  • Thanks! Honestly from reading about Jukito I'd recommend just making two separate tests. Alternatively you may be able to use `bindMany`, then check in the test method if the current user is logged in or not. – Tavian Barnes Jun 11 '14 at 17:33