I have mocked another class method called Which is called at production like new B().somemethod (arg) has return type void and newD().anymenthod() it has return type inputstream
In the test method, I am doing mocking Like donothing().when(b). somemethod ();
And
When(d.anymehod()).thenreturn(inputstream);(here inputstrem i am providing)
Here I already did #Mock B b;
#Mock D d;
Here my test case run successfully but mocked method was also called at that time.
Here I didn't want to alter the production code only test cases implementation can be altered.
class TestSystem {
#InjectMock
System sys;
#Mock
B b;
#Mock
D d;
#BeforeEach
void setup() {
MockitoAnnotation.openMocks(this);
}
#Test
testModule() {
InputStrem input = null;
when(d.anymethod()).thenReturn(inputStrem);
doNothing().when(b).somemethod();
sys.module();
}
Class System{
public void module() {
//some code .....
new B().somemethod();
inputStrem = new D().anymethod(value);
}
Class B {
public void somemethod(){
//some code .....
}
}
Class D {
public InputStrem anymethod() {
//some code ......
}
}
Try to initialise Mock like this:
#InjectMocks
private System sys;
#Mock
B b;
#Mock
D d;
private AutoCloseable closeable;
#BeforeEach
void init() {
closeable = MockitoAnnotations.openMocks(this);
}
#AfterEach
void closeService() throws Exception {
closeable.close();
}
#Test
testModule(){...}
Related
I have the following scenario.
public class A {
//constructors
#Value(${useMethodA:false})
private boolean isUseMethodAEnabled;
public void func() {
if(isUseMethodAEnabled()) {
a();
} else {
b();
}
}
}
//methods a() and b()
public class B {
#Autowired
private A a;
public void funcPrincipal() {
A.a();
System.out.println("Method A.a() was called");
}
}
#RunWith(MockitoJUnitRunner.class)
public class BTest {
#InjectMocks
private B b;
#InjectMocks
#Spy
private A a = new A();
#Test
public void test() {
ReflectionTestUtils.setField(a, "isUseMethodAEnabled", true);
b.funcPrincipal();
// if A is annotated with #Spy -> the "isUseMethodAEnabled" is always false
}
}
See the above comment, please.
Is there any solution to change the "isUseMethodAEnabled" value from false to true using reflection?
If I switch to #Mock instead of #Spy everything works as expected. But for my test cases, I must use #Spy + #InjectMocks.
Here is my test class.
#ExtendWith(MockitoExtension.class)
class DishServiceTest {
static MockedStatic<DaoFactory> daoFactoryDummy;
static MockedStatic<FileUtil> fileUtilDummy;
#Mock
DaoFactory daoFactory;
#Mock
DishDao dishDao;
#Spy
DishService dishService;
#BeforeAll
static void setUp() {
fileUtilDummy = Mockito.mockStatic(FileUtil.class);
daoFactoryDummy = Mockito.mockStatic(DaoFactory.class);
}
#AfterAll
static void close() {
daoFactoryDummy.close();
fileUtilDummy.close();
}
#Test
void deleteWithImage_id0_success() {
daoFactoryDummy.when(ServiceManager::getInstance).thenReturn(daoFactory);
when(daoFactory.createDishDao()).thenReturn(dishDao);
long id = 2;
String deleteDir = "/dish-image/2";
dishService.deleteWithImage(id, deleteDir);
verify(dishDao, times(1)).delete(id);
fileUtilDummy.verify(() -> FileUtil.deleteDishFolder(deleteDir));
}
#Test
void update_idSet_success() {
daoFactoryDummy.when(ServiceManager::getInstance).thenReturn(daoFactory);
when(daoFactory.createDishDao()).thenReturn(dishDao);
Dish dish = new Dish(2, "testName",
"testDescription", Category.DRINKS, BigDecimal.TEN, "/image21");
dishService.saveOrUpdate(dish);
verify(dishDao, times(1)).update(dish);
verify(dishDao, times(1)).close();
}
}
I mock static methods like this because DishService class gets dao object from DaoFactory.
Here is an example of DishService method
public class DishService {
public void saveOrUpdate(Dish newDish) {
try (DishDao dishDao = DaoFactory.getInstance().createDishDao()) {
long newDishId = newDish.getId();
if (newDishId == 0) {
dishDao.save(newDish);
} else {
dishDao.update(newDish);
}
}
}
}
And of DaoFactory
public class JDBCDaoFactory extends DaoFactory {
DBManager dbManager = DBManager.getInstance();
UserDaoMapper userDaoMapper = new UserDaoMapper();
DishDaoMapper dishDaoMapper = new DishDaoMapper();
OrderDaoMapper orderDaoMapper = new OrderDaoMapper();
OrderItemDaoMapper orderItemDaoMapper = new OrderItemDaoMapper();
#Override
public UserDao createUserDao() {
return new JDBCUserDao(dbManager.getConnection(),
userDaoMapper);
}
#Override
public DishDao createDishDao() {
return new JDBCDishDao(dbManager.getConnection(), dishDaoMapper);
}
#Override
public OrderDao createOrderDao() {
return new JDBCOrderDao(dbManager.getConnection(), orderDaoMapper,
orderItemDaoMapper);
}
}
And here is the exception I have
org.mockito.exceptions.misusing.MissingMethodInvocationException:
Also, this error might show up because:
you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified. Mocking methods
declared on non-public parent classes is not supported.
inside when() you don't call method on mock but on some other object. at
service.DishServiceTest.update_idSet_success(DishServiceTest.java:61)
Here is the line 61
The strangest thing here is that tests pass when I run them seperately, but if i press run all tests in class I get the exception above.
using Spring 2.0.3.RELEASE, JUnit Jupiter 5.7.0, Mockito 3.3.3
try to test method method01 of class Class01:
public class Class01 {
private RestConnector con;
public Class01(){
con = RestConnector.getInstance();
}
public Response method01(String x) {
Class01 example = new Class01();
String x = example.isAuthenticated();
// more stuff after this
}
public String isAuthenticated() throws IOException {
// I do stuff
return "a string";
}
}
In the test class have tried
public class Class01Test{
#Mock private Class01 class01Mock;
#Spy #InjectMocks private Class01 class01;
#Test
public void test() throws Throwable {
doReturn("I returned").when(class01). ??? stuck here .. always goes into the isAuthenticated method
Response result = class01.method01("a string");
}
}
Currently the test is always running the real method isAuthenticated.
How to setup a mock for the field example in method method01 so that the execute skips going into method isAuthenticated?
try to test method method01 of class Class01
Then you don't need mocks.
#Test
public void test() throws Throwable {
Class01 c = new Class01();
Response expected = ... ;
assertEquals(c.method01("input"), expected);
}
If you want to inject behaviour into example variable, you need to move it to a field
public class Class01 {
private RestConnector con;
private Class01 inner;
public Class01(){
con = RestConnector.getInstance();
}
Class01(Class01 c) {
this();
this.inner = c;
}
public Response method01(String x) {
String x = inner.isAuthenticated();
// more stuff after this
}
Along with a Mock
#RunWith(MockitoJunitRunner.class)
public class Class01Test{
#Mock Class01 class01Mock;
#Test
public void test() throws Throwable {
Response expected = ... ;
when(class01Mock.isAuthenticated()).thenReture(expected); ... // TODO: Setup
Class01 c = new Class01(class01Mock); // pass in the mock
assertEquals(c.method01("input"), expected);
}
However, unclear why you need a nested object of the same class when you appear to only need this.isAuthenticated()
Ideally, you'd also mock the RestConnector
I have class class1, which has 2 member variables:
classA
{
private Boolean isEnable;
private Config config;
public classA(final Config config)
{
this.config = config;
isEnable = config.getEnablingStatus();
}
public classB fun()
{
// Do something!
// Return an object of classB!
}
}
I want to test the method fun, so I will have to write a test-class and a test method for that. But, how do I mock the method call config.getEnablingStatus(), while creating an object of type classA in the test class?
I am thinking of doing something like this [see the below piece of code].Is it correct? But what is the right way to do it?
TestClassForClassA:
TestClassForClassA
{
private Boolean isEnable;
#Mock
private Config config;
#InjectMocks
classA objA = new classA(config);
#Before
public void init()
{
initMocks(this);
}
public void test1Fun()
{
// Does doing this, put the value of isEnable as true in the objA for this test?
isEnable = true;
// Here write the code to test the method fun().
}
public void test2Fun()
{
// Does doing this, put the value of isEnable as false in the objA for this test?
isEnable = false;
// Here write the code to test the method fun().
}
}
Do not use #InjectMocks
Try something like this
public class TestClassForClassA {
#Mock
private Config config;
private ClassA objA;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1Fun() {
Mockito.when(config.getEnablingStatus()).thenReturn(true);
objA = new ClassA(config);
ClassB objB = objA.fun();
assertTrue(objB.isEnabled());
}
#Test
public void test2Fun() {
Mockito.when(config.getEnablingStatus()).thenReturn(false);
objA = new ClassA(config);
ClassB objB = objA.fun();
assertFalse(objB.isEnabled());
}
}
Testing class
stream list into map, where I get atribute from an element of this list
public class MyClass {
private final Map<String, IMyInterface> map;
public MyClass(final List<IMyInterface> list) {
this.map = list.stream().collect(Collectors.toMap(IMyInterface::getUniqueName, i -> i));
}
}
Test
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#InjectMock
private MyClass instance;
#Spy
private ArrayList<IMyInterface> list;
#Mock
private A a;
#Mock
private B b;
#Before void setUp() throws Exception {
list.add(a);
list.add(b);
}
}
Or Test
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Spy
private ArrayList<IMyInterface> list;
#Mock
private A a;
#Mock
private B b;
private class MockedClass extends MyClass {
MockedClass(List<IMyInterface> list) {
super(list);
}
}
#Before void setUp() throws Exception {
list.add(a);
list.add(b);
}
}
How to get injected Map after execute constructor? I have to test this class and use map object
EDIT:
IMyInterface::getUniqueName()
is a method in interface
objects A and B implements IMyInterface
I want to collect injected list into map
When I add elements into list, I got it in debugging mode in my tested class, but when debugging mode is on
list.stream().collect(Collectors.toMap(IMyInterface::getUniqueName(), i -> i));
it stop
The correct answer is that should I mock A and B in my #Before
private A a;
private B b;
#Before
public void setUp() throws Exception {
a = new A(mock.Service.class); // cause it have an argument
b = new B(mock.Service.class); // cause it have an argument
list.add(a);
list.add(b);
}