I'm New in Mocking.
I've a service I'm trying to call is let say name A, I need to test someMethod.
#Service
public class A {
private Logger logger = LoggerFactory.getLogger(getClass());
private final CoreXReader coreXReader;
#Autowired
B b;
#Autowired
C c;
#Async
public void someMethod(Config config) throws Exception {
pushConfig(config);
}
private void pushConfig(Config config) throws Exception {
String url = config.getBaseurl() + config.getId();
ABCRestClient restClient = new ABCRestClient(url);
String jobJson = restClient.callRestMethod(HttpMethod.GET, "");
}
}
sample of ABCRestClient
public class ABCRestClient {
private Logger logger = LoggerFactory.getLogger(getClass());
private String url;
public ABCRestClient(String url) {
this.url = url;
}
public String callRestMethod(HttpMethod method, String payload) throws Exception {
someresponse="example response";
return someresponse;
}
}
I'm trying to test by creating mockSpy but it still Calling its 'callRestMethod'
#RunWith(SpringRunner.class)
#SpringBootTest // (webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
#Autowired
private A a;
private Logger logger = LoggerFactory.getLogger(getClass());
#Before
public void prepareMockDataForService() throws Exception {
ABCRestClient apiClient = new ABCRestClient(config.getBaseurl() + config.getId() );
ABCRestClient apiClientSpy=Mockito.spy(apiClient);
doReturn(getCallResponse()).when(apiClientSpy).callRestMethod(HttpMethod.GET, "");
}
#Test
public void TestPushConfig() throws Exception {
a.someMethod(StubDataGenerator.getConfig());
}
private String getCallResponse() {
return "{"msg":"sample response"}";
}
}
i'm not sure what I'm doing wrong here why its calling the actual callRestMethod as i already create a spy .
I tried using this too Mockito.doReturn(getCallResponse()).when(apiClientSpy.callRestMethod(HttpMethod.GET, ""))
Also, is there any difference in these two statement if I use it Mockito.doReturn() or directly doReturn()? In my case both seems behaving same.
Before I tried with this as well when().thenReturn(); but I read somewhere that use when().thenReturn() when you actually want to make call. Please correct if my understanding is wrong.
You can try mock instead of spy:
#RunWith(SpringRunner.class)
#SpringBootTest // (webEnvironment=
SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
#Autowired
private A a;
private Logger logger = LoggerFactory.getLogger(getClass());
#Before
public void prepareMockDataForService() throws Exception {
ABCRestClient apiClientSpy=Mockito.mock(ABCRestClient.class);
doReturn(getCallResponse()).when(apiClientSpy).callRestMethod(HttpMethod.GET, "");
}
#Test
public void TestPushConfig() throws Exception {
a.someMethod(StubDataGenerator.getConfig());
}
private String getCallResponse() {
return "{"msg":"sample response"}";
}
}
Related
How can I mock this condition using Mockito in spring boot.
#Autowired
private Config config;
if (!config.getAllowedFileFormats().contains(FilenameUtils.getExtension(multipartFile.getOriginalFilename()) {
}
I tried using this but this seems to not be working.
#Mock
private Config config; Mockito.when(config.getAllowedFileFormats().contains(Mockito.anyString())).thenReturn(Boolean.valueOf(true));
Any Solutions.
Functionally your code is exactly the same as the following:
static class SomeClass {
#Autowired
private Config config;
void method(MultipartFile multipartFile) {
String filename = multipartFile.getOriginalFilename();
Set<String> allowedFormats = config.getAllowedFileFormats();
if (!allowedFormats.contains(FilenameUtils.getExtension(filename))) {
}
}
}
So you can either:
Mock every method in the chain:
#Test
void test() {
Set<String> allowedFormats = new HashSet<>();
allowedFormats.add(".exe");
MultipartFile multipartFile = /* get your file here */ ;
Mockito.when(multipartFile.getOriginalFilename()).thenReturn("some.exe");
Mockito.when(config.getAllowedFileFormats()).thenReturn(allowedFormats);
myClass.method(multipartFile);
//verify
}
You can also static mock FilenameUtils.getExtension( but imo that's pointless as it's a helper without side effects.
Or you can pull that out into a separate method and just mock that.
#Test
void test() {
SomeClass myClassSpy = Mockito.spy(new SomeClass());
MultipartFile multipartFile = /* get your file here */ ;
Mockito.when(myClassSpy.verifyAllowedFormat(multipartFile)).thenReturn(true);
myClassSpy.method(multipartFile);
//verify
}
static class SomeClass {
#Autowired
private Config config;
void method(MultipartFile multipartFile) {
if (!verifyAllowedFormat(multipartFile);) {
}
}
boolean verifyAllowedFormat(MultipartFile file) {
return config.getAllowedFileFormats()
.contains(FilenameUtils.getExtension(multipartFile.getOriginalFilename()));
}
}
I am struggling at wrting unit test, when I test my code block, it says : constructor error
my code below;
#Component
public class CodeConfigBuilder {
#Value("${promoConfig.prefix.length}")
private Integer prefixLength;
public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
prefixAndPostFixControlAccordingToLength(promoRequest);
}
private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) {
if (promoRequest.getPostfix() != null) {
int lengthControl = prefixLength + promoRequest.getPostfix().length();
if (lengthControl >= promoRequest.getLength()) {
throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
}
}
}
public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest)
}
my yml configuration below;
#========= Promo Config ========== #
promoConfig:
prefix:
length: 3
my service below;
public void validateRequest(PromoRequest promoRequest) {
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
}
I have a created PropertySourceResolver class
#Value("${promoGenerationConfig.prefix.length}")
private Integer prefixLength;
and my test class below;
#ExtendWith(SpringExtension.class)
class CodeConfigBuilderTest {
private final PromonRequest promoRequest;
private final PropertySourceResolver propertySourceResolver;
private final PromoService promoService;
private final Request request;
public CodeConfigBuilderTest(PromonRequest promoGenerationRequest, PropertySourceResolver propertySourceResolver, PromoService promoService, Request request) {
this.PromonRequest = PromonRequest ;
this.propertySourceResolver = propertySourceResolver;
this.promoService = promoService;
this.request = request;
}
#Test
void prefixAndPostFixControlAccordingToLength() {
promoService.validateRequest(promoRequest);
int lengthControl = propertySourceResolver.getPrefixLength() + promoRequest.getPostfix().length();
Assertions.assertTrue(true, String.valueOf(lengthControl));
}
I have tried many things but my code does not pass the test it says "org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter"
any help, thank you
I'm not 100% but IMHO you can't use constructor injection in unit tests.
Use this instead:
#SpringBootTest
class CodeConfigBuilderTest {
#Autowired
private PromonRequest promoRequest;
#Autowired
private PropertySourceResolver propertySourceResolver;
#Autowired
private PromoService promoService;
#Autowired
private Request request;
Below is main code consist of one util class and service class using it
#PropertySource("classpath:atlas-application.properties")
public class ApacheAtlasUtils {
#Value("${atlas.rest.address}")
private String atlasURL;
#Value("${atlas.rest.user}")
private String atlasUsername;
#Value("${atlas.rest.password}")
private String atlasPassword;
private AtlasClientV2 client;
public AtlasClientV2 createClient() {
if (client == null) {
return new AtlasClientV2(new String[] {atlasURL}, new String[] {atlasUsername, atlasPassword});
} else {
return client;
}
}
}
Service Class is below :-
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
I am writing unit test for service method and I am getting exception for createClient method asking for values for url, username and password which should not happen as this should be mocked but the mocking is giving me below error
java.lang.IllegalArgumentException: Base URL cannot be null or empty.
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:141)
at org.apache.atlas.AtlasServerEnsemble.<init>(AtlasServerEnsemble.java:35)
at org.apache.atlas.AtlasBaseClient.determineActiveServiceURL(AtlasBaseClient.java:318)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:460)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:448)
at org.apache.atlas.AtlasBaseClient.<init>(AtlasBaseClient.java:132)
at org.apache.atlas.AtlasClientV2.<init>(AtlasClientV2.java:82)
at com.jlr.stratus.commons.utils.ApacheAtlasUtils.createClient(ApacheAtlasUtils.java:40)
at com.jlr.stratus.rest.service.impl.FileSearchService.findFilesWithPages(FileSearchService.java:49)
The Test code is as follows:-
private FileSearchService fileSearchService;
#Spy
private ApacheAtlasUtils apacheAtlasUtils;
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
fileSearchService = new FileSearchService();
}
#Test
public void findFilesWithPages_searchAll() throws AtlasServiceException {
Mockito.doReturn(client).when(apacheAtlasUtils).createClient();
service.search(queryParent,pageable);
}
Your idea with spying is adequate (you can even go for mocking if you do not actually need any true implementation of that class).
The problem lies in the implementation:
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
Instead of having the ApacheAtlasUtils as an instance variable (or a supplier method) you create the instance on the fly.
Mockito is not smart enough to catch that operation and replace the real object with you spy.
With the supplier method you can set up your test as follows:
#Spy
private FileSearchService fileSearchService = new FileSearchService();
#Spy
private ApacheAtlasUtils apacheAtlasUtils = new ApacheAtlasUtils();
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
doReturn(apacheAtlasUtils).when(fileSearchService).getApacheUtils();
}
in your SUT:
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = getApacheUtils().createClient();
//some code
}
ApacheAtlasUtils getApacheUtils(){
return new ApacheAtlasUtils();
}
I am trying mockito.verify() feature, the method invocation is only once but verify is showing invocation 3 times. The unit test has only one test, to ensure no other way this test get affected.
Mockito.verify(utilClass, Mockito.times(1)).hello(); /// but invocation is 3 times, is the error
I have tried using log, which is showing invocation is once. Added deliberate calling method utilClass.hello() more than once, then showing correct no of invocations.but in the given code where it is called once, is showing as called 3 times.
Class to be tested:
#Component
public class UtilClass {
private static final Logger logger = LoggerFactory.getLogger(UtilClass.class);
public String hello() {
logger.info("hello method invoked");
return "Hello World,"+ hi();
}
private String hi() {
logger.info("hi method invoked");
return "Hi All";
}
}
#Component
public class ClassWithDependency {
#Autowired
private UtilClass utilClass;
public String welcome() {
String msg = utilClass.hello();
return msg;
}
}
Test case
#InjectMocks
private ClassWithDependency classWithDependency;
#Mock
private UtilClass utilClass;
#Before
public void init() throws Exception {
PowerMockito.when(utilClass,"hi").thenReturn("Hi Java");
PowerMockito.when(utilClass.hello()).thenCallRealMethod();
}
#Test
public void testMock() throws Exception {
final String msg = classWithDependency.welcome();
final String msgExpected = "Hello World,Hi Java";
logger.info("welcome method called:{}",msg);
PowerMockito.verifyPrivate(utilClass, Mockito.times(1)).invoke("hi");
Mockito.verify(utilClass, Mockito.times(1)).hello();
Assert.assertTrue(msg.equals(msgExpected));
}
I am expecting the mockito.verify to be successful, but getting error
org.mockito.exceptions.verification.TooManyActualInvocations:
utilClass.hello();
Wanted 1 time:
-> at com.sd.demo.powermock.test.injectmock.InjectMockTest.testMock(InjectMockTest.java:54)
But was 3 times:
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
at com.sd.demo.powermock.test.injectmock.InjectMockTest.testMock(InjectMockTest.java:54)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
.............
Finally make the test working, the solution is 'SPY'.. Spy on util class, so that not to tell which method to make real call. I am not sure how to inject spy, so used a setter..
#InjectMocks
private ClassWithDependency classWithDependency;
private UtilClass mockUtil;
#Before
public void init() throws Exception {
UtilClass utilClass = new UtilClass();
mockUtil = PowerMockito.spy(utilClass);
classWithDependency.setUtilClass(mockUtil);
}
#Test
public void testMock() throws Exception {
PowerMockito.when(mockUtil,"hi").thenReturn("Hi Java");
final String msg = classWithDependency.welcome();
final String msgExpected = "Hello World,Hi Java";
logger.info("welcome method called:{}",msg);
PowerMockito.verifyPrivate(mockUtil, Mockito.times(1)).invoke("hi");
Mockito.verify(mockUtil, Mockito.times(1)).hello();
Assert.assertTrue(msg.equals(msgExpected));
}
I am trying to mock a method call in controller class, but while trying to run the code, the original class is called.
I am able to successfully mock methods in service layer class.
My controller has as an instance of Util class. I want to mock the methods inside Util class. Even after trying the same way i have successfully mocked the methods in service layer, while executing the test cases, the original method is invoked.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = { InitializerTest.class,
MultiHttpSecurityConfig.class, CustomerConfigTest.class,
EmployeeConfigTest.class, DataSourcePropertiesTest.class,MyController.class })
#WebAppConfiguration
#TestExecutionListeners(listeners = { ServletTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
WithSecurityContextTestExecutionListener.class })
#ActiveProfiles("test")
public class MyControllerAbstractTest {
private static final Logger LOG = LoggerFactory
.getLogger(MyControllerAbstractTest.class);
#Autowired
public WebApplicationContext context;
#Autowired
public Util util;
#Autowired
public MyController myController;
public static final String path = "D:/jks/";
public static final String client1Jks = path + "client1Jks.jks";
public static final String trustJks = path + "trustJks.jks";
public static char[] passwd={'p','a','l'};
KeyStore trustStore=null;
public void setupSSLMock() throws KeyStoreException, IOException,
NoSuchAlgorithmException, CertificateException {
InputStream trustStoreStream = Thread.currentThread()
.getContextClassLoader().getResourceAsStream(trustJks);
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStoreStream, passwd);
RestAssured.config = RestAssured.config()
.sslConfig(
new SSLConfig().with().trustStore(trustStore).and()
.keystore(client1Jks, passwd.toString())
.allowAllHostnames());
}
#Before
public void setUp() {
//RestAssured.useRelaxedHTTPSValidation();
if (!isSetup) {
this.util=(Util)context.getBean("util");
util=Mockito.mock(Util.class);
myController=(MyController)context.getBean(MyController.class);
ReflectionTestUtils.setField(myController, "util",
Util);
MockitoAnnotations.initMocks(this);
RestAssuredMockMvc.mockMvc = MockMvcBuilders
.webAppContextSetup(context).apply(springSecurity())
.build();
isSetup = false;
}
}
public void createValidatorMock(){
org.mockito.Mockito.stub(
Util
.validateSslCertificate(org.mockito.Matchers.any())).toReturn(
null);
// org.mockito.Mockito.when(
// Util
// .validateSslCertificate(org.mockito.Matchers.any())).thenReturn(
// null);
}
public String invokeXMLAPI(String requestJson, String url) {
ValidatableMockMvcResponse reponse = given().
log().all()
.contentType(TestConstants.APPLICATION_XML).body(requestJson)
.when().post(url).then().statusCode(HttpServletResponse.SC_OK);
return reponse.extract().asString();
}
}
This is the test method:-
#Test
#WithMockUser(roles = "customer")
public void testXMLMessages()
throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException {
String url=TestConstants.XML_API;
setupSSLMock();
createValidatorMock();
invokeXMLAPI(requestJson,url)
}
Is there a different way to mock for the controller later, as it is annotated differently.