0

This test is failing but I don't know why or how to fix it. If I hit a break point and call mockingContext.getBean(Repository.class), it does return my mock object, but for some reason the ProductionCode returned in createProductionCodeWithMock still has the real Repository autowired into it. I can only suspect that I need to do something special/extra to have an effect on autowired beans, but I don't know what it is. Why isn't this test passing, and how can I make it pass?

For what it's worth, I'm well aware of all the answers to this question. I still want to know why this test isn't working. I am using Spring 3.x.

Here's the test:

package mavensnapshot;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class ProductionCodeTest {

    @Test
    public void testReplaceRepositoryWithMock() {
        Repository mockRepository = mock(Repository.class);

        ProductionCode productionCode = createProductionCodeWithMock(mockRepository);
        productionCode.doSomething();

        verify(mockRepository).save();
    }

    private ProductionCode createProductionCodeWithMock(Repository mockRepository) {
        GenericApplicationContext mockingContext = new GenericApplicationContext();
        mockingContext.getBeanFactory().registerSingleton(Repository.class.getName(), mockRepository);
        mockingContext.setParent(new ClassPathXmlApplicationContext("/beans.xml"));

        return mockingContext.getBean(ProductionCode.class);
    }

}

Here's my production code:

package mavensnapshot;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("/beans.xml");
        ProductionCode productionCode = context.getBean(ProductionCode.class);
        productionCode.doSomething();
    }

}

package mavensnapshot;

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

@Service
public class ProductionCode {

    @Autowired
    private Repository repository;

    public void doSomething() {
        repository.save();
    }

}

package mavensnapshot;

import org.springframework.stereotype.Service;

@Service
public class Repository {

    public void save() {
        System.out.println("production code");
    }

}
Community
  • 1
  • 1
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • 1
    My guess, your service is in the `beans.xml`? Child contexts don't have an influence on the root context. – M. Deinum Jan 11 '15 at 08:00
  • Well my beans.xml only scans for annotations, so yeah. – Daniel Kaplan Jan 11 '15 at 09:12
  • 1
    Well as stated that isn't going to work as it doesn't see the bean. – M. Deinum Jan 11 '15 at 09:40
  • @M.Deinum ah, any work around you can think of? – Daniel Kaplan Jan 11 '15 at 09:44
  • Why do you need a context at all? It is a junit test not an integration test. Just create in instance of your service yourself and inject the dependency. If you use the special Mockito JUnit Runner you can use the `@InjectMocks` annotation for this. – M. Deinum Jan 11 '15 at 09:45
  • @M.Deinum ah well the real scenario is A depends on B, to C, to D and I want to mock out D without directly calling getters and setters down the chain to do it. I just want to test from A. `@InjectMocks` doesn't use spring so I'd have to set up this chain of dependencies by hand. I really want to avoid that. – Daniel Kaplan Jan 11 '15 at 09:49
  • Then maybe rethink your test you are basically doing an integration test then why not simply handle it like that. Use an in memory database and after the execution of your method check the content of the database. – M. Deinum Jan 11 '15 at 09:50

0 Answers0