dimanche 22 février 2015

Injecting Mockito mocks into beans returned through factory methods

I have the following set up:


A sample class that needs to be mocked during testing:



@Component
class MyConfig
{
public String getConfig()
{
return "RealValue";
}
}


An interface that defines a single method and has two implementations:



interface MyInterface
{
String myMethod();
}

class MyImpl1 implements MyInterface
{
private final MyInterface delegate;
private final MyConfig config;

public MyImpl1(final MyInterface delegate, final MyConfig config)
{
this.delegate = delegate;
this.config = config;
}

@Override
public String myMethod()
{
return this.getClass().getSimpleName() + ": " + config.getConfig() + ", " + delegate.myMethod() + ";";
}
}

class MyImpl2 implements MyInterface
{
private final MyConfig config;

public MyImpl2(final MyConfig config)
{
this.config = config;
}

@Override
public String myMethod()
{
return this.getClass().getSimpleName() + ": " + config.getConfig();
}
}


A factory class that prepares a bean of type MyInterface using the MyConfig object that is a spring bean injected into MyFactory:



@Component
class MyFactory
{
@Autowired
private MyConfig config;

// Factory method to create the bean.
@Bean(name = "myInterface")
protected MyInterface myInterface()
{
final MyImpl2 myImpl2 = new MyImpl2(config);
final MyImpl1 myImpl1 = new MyImpl1(myImpl2, config);
return myImpl1;
}

// A simple getter that prepares MyInterface on the fly.
public MyInterface getInterface()
{
final MyImpl2 myImpl2 = new MyImpl2(config);
final MyImpl1 myImpl1 = new MyImpl1(myImpl2, config);
return myImpl1;
}
}


A simple test case that checks if the mock version of MyConfig is getting into the bean created using @Bean or not:



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:application-context.xml"
})
public class SpringBeanMockExampleTest
{
@Mock
private MyConfig config;

@InjectMocks
@Autowired
protected MyFactory factory;

@Resource
private MyInterface myInterface;

@Before
public void setupMocks()
{
MockitoAnnotations.initMocks(this);
}

@Test
public void testBean()
{
Mockito.when(config.getConfig()).thenReturn("MockValue");
/**
* Fails as the return value is "MyImpl1: RealValue, MyImpl2: RealValue;"
*/
Assert.assertEquals("MyImpl1: MockValue, MyImpl2: MockValue;", myInterface.myMethod());
}

@Test
public void testGetter()
{
Mockito.when(config.getConfig()).thenReturn("MockValue");
Assert.assertEquals("MyImpl1: MockValue, MyImpl2: MockValue;", factory.getInterface().myMethod());
}
}


I expected the testBean method to pass also, but obviously the mock is not getting injected into the factory bean created in MyFactory. How can I fix this so that testBean works as expected?


Aucun commentaire:

Enregistrer un commentaire