I have below class scenario. While testing MyTestableClass, I wish to process Autowired class.
I would like to mock only variable in AutoWired class.
sample class is as below-
public class MyTestableClass {
#Autowired
private MyServiceClass service;
public void handleError(){
...
service.doSomething();
}
}
public class MyServiceClass {
#Autowired
private JMSChannel channel;
public void doSomething(){
System.out.println("Inside Service class");
.....
channel.isAvailable();
.....
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyTestableClassTest {
private MyTestableClass testClass= new MyTestableClass();
private JMSChannel channel;
#Before
public void init(){
channel= mock(JMSChannel.class);
when(channel.isAvailable()).thenReturn(Boolean.TRUE);
}
#Test
public void test(){
testClass.handleError();
}
}
For example, Console should give me "Inside Service class" before returning true.
Thanks in Advance !
You need to create and instance of your service (or a mock of it) and set its channel to your mocked one, then set MyTestableClass#service to this one. Something like:
#Before
public void init(){
channel= mock(JMSChannel.class);
when(channel.isAvailable()).thenReturn(Boolean.TRUE);
MyServiceClass service = new MyServiceClass();
ReflectionTestUtils.setField(service, "channel", channel);
myTestableClass = new MyTestableClass();
ReflectionTestUtils.setField(myTestableClass, "service", service);
}
with ReflectionTestUtils from spring-test (NB: you can use a setter instead)
Related
In the following case, can I test "MainServiceImpl"?
【What I want to do】
・Test target object is "MainServiceImpl".
・SubMainServiceImpl is used without mock.
・SubSubMainServiceImpl.subSubSayHello method is used with mock.
You may say "double autowired class is not recommended to mock." I know, but I want to know the above test is technically possible.
//Test Target Object
#Service
public class MainServiceImpl implements MainService {
#Autowired
private SubMainService subMainService;
#Override
public String mainSayHello() {
return "MainSayHello. Also..." + subMainService.subSayHello();
}
}
//MainServiceImpl depends on this class.
#Service
public class SubMainServiceImpl implements SubMainService {
#Autowired
private SubSubMainService subSubMainService;
#Override
public String subSayHello() {
return "SubSayHello. Also..." + subSubMainService.subSubSayHello();
}
}
//SubSubServiceImpl depends on this class.
#Service
public class SubSubMainServiceImpl implements SubSubMainService {
#Override
public String subSubSayHello() {
return "SubSubSayHello";
}
}
As a side note, I can mock direct-autowired class.
How can I mock "double" autowired class?
//Direct(not double) autowired class is mocked.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MockMainServiceTest {
#InjectMocks
MainServiceImpl mainService;
#Mock
SubMainService subMainService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void SubMainService_Mocked(){
doReturn("SubMainService_Mocked").when(subMainService).subSayHello();
Assert.assertThat(mainService.mainSayHello() ,is("MainSayHello. Also...SubMainService_Mocked"));
}
}
Technology
SpringBoot 2.5.4
JUnit 4.2
Java 1.8
I have a controller like this
#Path("/")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class AccountController implements CRUDController<Long, Account> {
private AccountDao accountDao;
private AccountService accountService;
#Inject
public AccountController(AccountDao accountDao, AccountService accountService) {
this.accountDao = accountDao;
this.accountService = accountService;
}
...
I'm injecting AccountDao and AccountService using
ResourceConfig config = new ResourceConfig()
.packages("controller", "exception")
.register(new MyDIBinder());
Where MyDIBinder is contains all the bindings (e.g
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
bind(accountDaoImpl).to(AccountDao.class);
)
Now I want to write a unit test for this controller, is it possible to inject the whole AccountController instance with all of it's transitive dependencies into the test?
Something like
#Inject
AccountController accountController;
You can use the main IoC container, and just explicitly inject the test class. Jersey uses HK2 as its DI framework, and its IoC container is the ServiceLocator, which has a method inject(anyObject) that can inject any objects with dependencies that are in its registry.
For example you could do something like
public class InjectionTest {
#Inject
private TestController controller;
#Before
public void setUp() {
final Binder b = new AbstractBinder() {
#Override
public void configure() {
bindAsContract(TestController.class);
}
};
final ServiceLocator locator = ServiceLocatorUtilities.bind(new TestBinder(), b);
locator.inject(this);
}
#Test
public void doTest() {
assertNotNull(controller);
String response = controller.get();
assertEquals("Hello Tests", response);
}
}
The ServiceLocatorUtilities class is a helper class that allows us to easily create the ServiceLocator, and then we just call inject(this) to inject the InjectionTest.
If it seems repetitive to do this for all your controller tests, you may want to create an abstract base test class. Maybe something like
public abstract class AbstractControllerTest {
protected ServiceLocator locator;
private final Class<?> controllerClass;
protected AbstractControllerTest(Class<?> controllerClass) {
this.controllerClass = controllerClass;
}
#Before
public void setUp() {
final AbstractBinder binder = new AbstractBinder() {
#Override
public void configure() {
bindAsContract(controllerClass);
}
};
locator = ServiceLocatorUtilities.bind(new TestBinder(), binder);
locator.inject(this);
}
#After
public void tearDown() {
if (locator != null) {
locator.shutdown();
}
}
}
Then in your concrete class
public class TestControllerTest extends AbstractControllerTest {
public TestControllerTest() {
super(TestController.class);
}
#Inject
private TestController controller;
#Test
public void doTest() {
assertNotNull(controller);
assertEquals("Hello Tests", controller.get());
}
}
If you spent some more time, I'm sure you could come up with a better abstract test class design. It was the first thing that came to mind for me.
Note: For anything request scoped, you mayb need to just mock it. When running the unit tests, there is no request context, so the test will fail.
See Also:
Using Jersey's Dependency Injection in a Standalone application
HK2 documentation
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
#BeforeClass
public static void doTest() {
ServiceLocator serviceLocator = ServiceLocatorUtilities.bind(new AbstractBinder() {
#Override
protected void configure() {
bindAsContract(YourClass1.class);
bindAsContract(YourClass2.class);
bindAsContract(YourClass3.class);
}
});
YourClass1 yourClass1 = serviceLocator.getService(YourClass1.class);
...
I am newbie in Java world, but it is very hard understand why not can I stub method of a mocked object...
#RunWith(MockitoJUnitRunner.class)
public class ChildBLLIT extends BaseInteractorIT {
#InjectMocks
private ChildBLL ChildBLL = Mockito.mock(ChildBLL.class);
#Before
public void setUp() {
ChildBLL.engine = engineMock;
}
/**
* Test of getZipStatistics method, of class ChildBLL.
*/
#Test
public void testGetZipStatistics() {
final String testZipStatisticsText = "DummyZipStatistics";
//This method will throw the null pointer exception
when(ChildBLL.engine.getZIPStatistics()).thenReturn(testZipStatisticsText);
ChildBLL.getZipStatistics();
verify(ChildBLL.engine).getZIPStatistics();
}
}
When I try to stub the getZIPStatistics() method I get always a null pointer exception, of course I get, because in the getZIPStatistics() method there is an private object, which is not mocked... it seems to me the Mockito does not mocking the private fields... and unfortunately this is from another project:
public class BaseIT {
#Mock
protected static FromOtherProject engineMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}
Here I mocked the engine variable, but then how can I mock/stub the getZIPStatistics() method? This is this method:
public class FromOtherProject {
//...
public final String getZIPStatistics() {
return ZIPStatistics.toString();
}
}
What can I do?
Let's assume a simple class...
public class Account {
public String getPassword() {
return "abc";
}
}
...and simple class that contains it...
public class AccountHolder {
private Account account;
public String getAccountPassword() {
return this.account.getPassword();
}
}
So now we have a simple base class for all Account based tests...
public class AccountBasedTest {
#Mock
protected Account account;
}
...and a class that actually tests the AccountHolder...
#RunWith(MockitoJUnitRunner.class)
public class AccountHolderTest extends AccountBasedTest {
#InjectMocks
private AccountHolder accountHolder;
#Test
public void getAccountPasswort_must_return_account_password() {
Mockito.when( this.account.getPassword() ).thenReturn ("xyz");
Assert.assertEquals("xyz", this.accountHolder.getAccountPassword());
}
}
And that's all. The #InjectMocks, etc. annotations will also look in the superclasses, so you get your mocked account and that account will be put into your AccountHolder. No need to call MockitoAnnotations.initMocks. It shouldn't hurt, but it's not needed because you are using the MockitoJUnitRunner already, which does exactly that.
I'm trying to write JUnit tests for some code that is normally managed with Spring.
Let's say I have this:
#Configurable
public class A {
#Autowired MyService service;
public void callA() { service.doServiceThings(); }
}
I can write a test for this class using Mockito and PowerMock like this:
#RunWith(PowerMockRunner.class)
public class ATest {
#Spy MyService service = new MyService();
#Before void initMocks() { MockitoAnnotations.initMocks(this); }
#Test void test() {
#InjectMocks A a = new A(); // injects service into A
a.callA();
//assert things
}
}
But now I run into a case when some other class constructs instances of A:
public class B {
public void doSomething() {
A a = new A(); // service is injected by Spring
a.callA();
}
}
How do I make service get injected into instances of A created inside a B method?
#RunWith(PowerMockRunner.class)
public class BTest {
#Spy MyService service = new MyService();
#Before void initMocks() { MockitoAnnotations.initMocks(this); }
#Test testDoSomething() {
B b = new B();
// is there a way to cause service to be injected when the method calls new A()?
b.doSomething();
// assert things
}
}
Field injection is bad but still there's one thing that you can do to easily stub that A instantiation (or maybe I misunderstood sth). Make B have an AFactory injected via constructor.
public class B {
private final AFactory aFactory;
public B(AFactory aFactory) {
this.aFactory=aFactory;
}
public void doSomething() {
A a = aFactory.getA();
a.callA();
}
}
And then you can create a Mock of aFactory and inject it to B via constructor.
I'm new to mock testing.
I want to test my Service method CorrectionService.correctPerson(Long personId).
The implementation is not yet written but this it what it will do:
CorrectionService will call a method of AddressDAO that will remove some of the Adress that a Person has. One Person has Many Addresses
I'm not sure what the basic structure must be of my CorrectionServiceTest.testCorrectPerson.
Also please do/not confirm that in this test i do not need to test if the adresses are actually deleted (should be done in a AddressDaoTest), Only that the DAO method was being called.
Thank you
Cleaner version:
#RunWith(MockitoJUnitRunner.class)
public class CorrectionServiceTest {
private static final Long VALID_ID = 123L;
#Mock
AddressDao addressDao;
#InjectMocks
private CorrectionService correctionService;
#Test
public void shouldCallDeleteAddress() {
//when
correctionService.correct(VALID_ID);
//then
verify(addressDao).deleteAddress(VALID_ID);
}
}
A simplified version of the CorrectionService class (visibility modifiers removed for simplicity).
class CorrectionService {
AddressDao addressDao;
CorrectionService(AddressDao addressDao) {
this.addressDao;
}
void correctPerson(Long personId) {
//Do some stuff with the addressDao here...
}
}
In your test:
import static org.mockito.Mockito.*;
public class CorrectionServiceTest {
#Before
public void setUp() {
addressDao = mock(AddressDao.class);
correctionService = new CorrectionService(addressDao);
}
#Test
public void shouldCallDeleteAddress() {
correctionService.correct(VALID_ID);
verify(addressDao).deleteAddress(VALID_ID);
}
}