Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have an AuthenticationManager.authenticate(username,password) method that gets called in someMethod of a SomeService under test. The AuthenticationManager is injected into SomeService:

@Component
public class SomeService {
    @Inject
    private AuthenticationManager authenticationManager;

    public void someMethod() {
        authenticationManager.authenticate(username, password);
        // do more stuff that I want to test
    }
}

Now for the unit test I need the authenticate method to just pretend it worked correctly, in my case do nothing, so I can test if the method itself does the expected work (Authentication is tested elsewhere according to the unit testing principles, however authenticate needs to be called inside that method)

So I am thinking, I need SomeService to use a mocked AuthenticationManager that will just return and do nothing else when authenticate() gets called by someMethod(). How do I do that with PowerMock (or EasyMock / Mockito, which are part of PowerMock)?

Or is there another way to tell Spring to use some Mock instead of the real deal, when injeeting the AuthenticationManager into SomeService?

Or is my design wrong?

Thanks!


Edit - found a solution, would like to hear comments

So I found a nice way to inject a mock without having to use a setter or package level:

@RunWith(PowerMockRunner.class)
public class TestOrderService {

    @Mock
    private AuthenticationManager authenticationManager;

    @InjectMocks 
    private OrderService orderService = new OrderService();

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        Mockito.doNothing().when(this.authenticationManager).authenticate(null, null);
    }

    @Test
    public void testOrderService() {
        orderService.save(null, null, null);
    }
}

with OrderService like this:

public void save(String username, Order order) {
    authenticationManager.authenticate(username, password);
    // do something with the order...
}

Now the save method will call authenticate on the mock and the mock does nothing leaving me free to test the actual work inside my service method (which actually is calling a manager method but that was not the point ;) )

share|improve this question
add comment

1 Answer

I personally don't use spring on the unit testing side (except maybe a single test to verify that the application context loads properly). Instead I use setter methods to manually wire the mocks (actually I use project lombok's @Setter annotation), OR if I'm using @Autowired I make the member variables package scoped so the unit test can directly set the values.

I don't see how you're going to get things like Mockito to work via dependency injection, because you'll always be new-ing your object inside the unit test and then creating mock behaviors for the methods. Also, you don't lose much by doing it this way, because you'll only need to setup direct dependencies of the class under test (because they're mocks), which is much easier than what spring DI does, which is recursive dependency creation and wiring on real objects.

share|improve this answer
    
Good point actually. Was wondering if I couldn't reduce the testing time by removing the spring context from the equation... How about using reflections to access the private beans? Or maybe there's a frameworks that wraps this behaviour? I don't feel comfortable creating a security risk by making the beans package scope and I don't like to add setters just so I can unit test a class when I don't need them otherwise... –  Pete Feb 14 '12 at 19:46
    
That's why I like Lombok. You add an annotation and it generates the setter method. The setter method is still there but I don't have to look at it every time I edit the file so it's much less annoying –  Kevin Feb 15 '12 at 3:04
    
Found a nice solution without a setter or spring context. Would like to hear your opinion. –  Pete Feb 15 '12 at 8:37
1  
Nice I hadn't seen @InjectMocks before. I'm going to start using that instead... –  Kevin Feb 16 '12 at 5:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.