I have a project by name Utility and it has a class by name Util as below:
public class Util {
public static String verify() {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpGet getRequest = new HttpGet("Endpoint");
HttpResponse response = httpClient.execute(getRequest);
// Parsing the response as String
String resp = .......
return resp;
}
}
I have another project by name Consumer and it has a class by name Service as below:
public class Service {
public String verify() {
String resp = Util.verify();
return resp;
}
}
I have added Utility as a dependency for Consumer as:
<dependency>
<groupId>com.my.company</groupId>
<artifactId>utility</artifactId>
<version>0.0.1</version>
<scope>provided</scope>
</dependency>
I have a unit test case for the Service class where I am mocking the Util class with PowerMockito as:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Util.class })
public class ServiceTest {
Service service = new Service();
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(Util.class);
PowerMockito.when(Util.verify()).thenReturn("mockedResponse");
}
#Test
public void testVerify() {
String resp = service.verify();
assertEquals(resp, "mockedResponse");
}
}
This test throws NotFoundException for ProtocolSocketFactory. Does anyone know why I see this exception? I am trying to mock the Util class, but PowerMockito tries to initialize the class before mocking it. If I add HttpClient as a dependency in pom.xml for project Consumer, then the error goes away and the mocking is successful.
The Powermockito version I am using is 1.6.2
java.lang.IllegalStateException: Failed to transform class with name com.my.company.Util. Reason: cannot find org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:266)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
Caused by: javassist.CannotCompileException: cannot find org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at javassist.expr.NewExpr.replace(NewExpr.java:215)
at org.powermock.core.transformers.impl.MainMockTransformer$PowerMockExpressionEditor.edit(MainMockTransformer.java:418)
at javassist.expr.ExprEditor.loopBody(ExprEditor.java:212)
at javassist.expr.ExprEditor.doit(ExprEditor.java:91)
at javassist.CtClassType.instrument(CtClassType.java:1431)
at org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:74)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:251)
... 55 more
Caused by: javassist.NotFoundException: org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at javassist.ClassPool.get(ClassPool.java:450)
at javassist.bytecode.Descriptor.toCtClass(Descriptor.java:592)
at javassist.bytecode.Descriptor.getParameterTypes(Descriptor.java:439)
at javassist.expr.NewExpr.replace(NewExpr.java:188)
... 61 more
Related
I've written a bit of middleware in an ASP.NET Core site and I'm trying to unit test it, mainly by following this guide that uses Moq.
My problem is finding an NUnit/NSubstitute equivalent for new DefaultHttpContext(). Substituting HttpContext will trigger the middleware, but it passes the try. I presume this is because of the issue quoted below. Does NUnit have a function to create a real HttpContext, or am I looking at a lot more infrastructure to achieve this?
I am sending an instance of DefaultHttpContext to the Invoke method. I can't use a mocked HttpContext in this scenario because the first middleware (the lambda function that we passed to the constructor) will need to write to the response. Hence the HttpResponse needs to be a real object not mocked.
Here is the code for my Test
[TestFixture]
public class ExceptionHelperTests
{
private IErrorRepository errorRepository;
private ExceptionHandler handler;
[SetUp]
public void Setup()
{
errorRepository = Substitute.For<IErrorRepository>();
}
[Test]
public async void Given_AnExceptionHappens_Then_ItShouldBeLogged()
{
// Arrange
const string username = "aUser";
var user = Substitute.For<ClaimsPrincipal>();
user.Identity.Name.Returns(username);
handler = new ExceptionHandler(
next: async (innerHttpContext) =>
{
innerHttpContext.User = user;
},
repository: errorRepository);
// Act
await handler.Invoke(new DefaultHttpContext());
// Assert
errorRepository.Received().LogException(Arg.Any<string>(), Arg.Any<Exception>(), Arg.Is(username));
}
}
Here is the IErrorRepository
public interface IErrorRepository
{
Exception LogException(string message, Exception ex, string userId);
void LogMessage(string message, string errorDetail, string userId);
}
And here is the middleware (with a simplified HandleException):
public sealed class ExceptionHandler
{
private readonly RequestDelegate _next;
private readonly IErrorRepository repository;
public ExceptionHandler(RequestDelegate next, IErrorRepository repository)
{
_next = next;
this.repository = repository;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
HandleException(ex, context.User.Identity.Name);
}
}
public void HandleException(Exception ex, string userId)
{
repository.LogException("An unhandled exception has occurred.", ex, userId);
}
}
DefaultHttpContext is just the default implementation of HttpContext abstract class.
You just could do
var HttpContextSub = Substitute.For<HttpContext>();
I am using Mockito + PowerMock to write a simple unit test for the following singleton class:
public class MyService {
private static MyService service;
private List<School> schoolList;
private MyService(){
// test case error complains here!
School school = new School();
schoolList.add(school);
}
public static Singleton getInstance( ) {
return service;
}
protected static void printSchool( ) {
School school = schoolList.get(0);
print(school);
}
}
My Test case:
#RunWith(PowerMockRunner.class)
public class MyServiceTest {
#PrepareForTest({MyService.class})
#Test
public void testPrintSchool() {
// enable mock static function
PowerMockito.mockStatic(MyService.class);
MyService mockService = PowerMockito.mock(MyService.class);
PowerMockito.when(MyService.getInstance())
.thenReturn(mockService);
}
}
I run my test, but got the following error:
java.lang.RuntimeException: Invoking the beforeTestMethod method on PowerMock test listener org.powermock.api.extension.listener.AnnotationEnabler#3ab19451 failed.
at com.xyz.MyService.<init>(MyService.java:12)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.mockito.internal.util.reflection.FieldInitializer$ParameterizedConstructorInstantiator.instantiate(FieldInitializer.java:257)
at org.mockito.internal.util.reflection.FieldInitializer.acquireFieldInstance(FieldInitializer.java:124)
at org.mockito.internal.util.reflection.FieldInitializer.initialize(FieldInitializer.java:86)
at org.mockito.internal.configuration.injection.ConstructorInjection.processInjection(ConstructorInjection.java:52)
...
As you can see, the error complains about MyService.java:12 line 12, that is the line School school = new School(); in MyService constructor.
Why I get this error, how to get rid of it?
#PrepareForTest({MyService.class}) is a class level annotation.
You should add it at the same location as #RunWith(PowerMockRunner.class)
You can find more information at their github
I have a web serivce class which need to unit tested.
Here is class which is under test
public class ValidatePaymentMessage {
public CsmValidationResultX validatePaymentmsg(String csmName, String base64PayloadXML){
//Call Web Service to validate Payment
CsmValidationResultX responseMsg=null;
PaymentManagerWebService paymentManagerWebService = new PaymentManagerWebService();
PaymentManagerWebServiceImpl serviceAddrs = paymentManagerWebService.getPaymentManagerWebServicePort();
try {
responseMsg = serviceAddrs.validatePayment(csmName, base64PayloadXML);
} catch (MPMWebServiceException e) {
e.printStackTrace();
}
return responseMsg;
}
}
Here is my Junit class
public class ValidatePaymentMessageTest {
#Test
public void testValidatePaymentmsg() throws MPMWebServiceException {
CsmValidationResultX csmResult= EasyMock.createMock(CsmValidationResultX.class);
PaymentManagerWebServiceImpl paymentManagerImpl = EasyMock.createMock(PaymentManagerWebServiceImpl.class);
EasyMock.expect(paymentManagerImpl.validatePayment("SEPA","BASE64XML")).andReturn(csmResult).anyTimes();
PaymentManagerWebService paymentManager = EasyMock.createMock(PaymentManagerWebService.class);
EasyMock.expect(paymentManager.getPaymentManagerWebServicePort()).andReturn(paymentManagerImpl).anyTimes();
ValidatePaymentMessage validatePayment=new ValidatePaymentMessage();
CsmValidationResultX response = validatePayment.validatePaymentmsg("SEPA", "base64PayloadXML");
System.out.println(response.getCsmValidationResult().isValid());
}
}
When I run this Junit it is calling actual web service instead of mocked one's.So Please let me know how can i resolve this problem.
You are still instantiating a real PaymentManagerWebService in validatePaymentmsg(), so the mocks do not help. You can't mock construction of local variables with EasyMock, but you can with PowerMock. So if changing the code to receive and instance of PaymentManagerWebService is not an option, mock its construction with PowerMock.
#RunWith(PowerMockRunner.class)
#PrepareForTest(ValidatePaymentMessage.class)
public class ValidatePaymentMessageTest {
#Test
public void testValidatePaymentmsg() throws MPMWebServiceException {
// .....
PowerMock.expectNew(PaymentManagerWebService.class).andReturn(paymentManager);
//....
}
}
i have a service method that get session attribute and i want to make unit test for this service method and i was wondering how to mock the HttpSession in jsf.
1- use the FacesContextMocker class:
public abstract class FacesContextMocker extends FacesContext {
private FacesContextMocker() {}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE).when(context).release();
return context;
}
}
2- in the test class #Before method do the following:
FacesContextMocker.mockFacesContext();
ExternalContext externalContext = Mockito.mock(ExternalContext.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext())
.thenReturn(externalContext);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(
FacesContext.getCurrentInstance().getExternalContext()
.getRequest()).thenReturn(request);
HttpSession httpSession = Mockito.mock(HttpSession.class);
Mockito.when(GeneralUtils.getHttpSession()).thenReturn(httpSession);
3- the getHttpSession method is as follows:
public static HttpSession getHttpSession() {
return ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession();
}
4- in the test method do the following:
Mockito.when(
GeneralUtils.getHttpSession().getAttribute(
"userID")).thenReturn("1");
5- this is assuming that in your service method that you are making the unit test for you have code like:
String currentUserID = (String) GeneralUtils.getHttpSession()
.getAttribute(userID);
I've used this technique before and specifying all the configuration explicitly. The log indicates it's creating the datasource and loading the scripts:
o.s.j.d.e.EmbeddedDatabaseFactory - Starting embedded database: url='jdbc:h2:mem:balancer;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
o.s.j.d.i.ScriptUtils - Executing SQL script from class path resource [db/migration/V1_0001__create_queue_server_table.sql]
o.s.j.d.i.ScriptUtils - Executed SQL script from class path resource [db/migration/V1_0001__create_queue_server_table.sql] in 20 ms.
o.s.j.d.i.ScriptUtils - Executing SQL script from class path resource [db/migration/V1_0002__queue_server_entries.sql]
o.s.j.d.i.ScriptUtils - Executed SQL script from class path resource [db/migration/V1_0002__queue_server_entries.sql] in 8 ms.
o.s.o.j.LocalContainerEntityManagerFactoryBean - Building JPA container EntityManagerFactory for persistence unit 'default'
I am able to invoke the REST webservice and the call goes through to the Repository but nothing is returned. The application works fine when connecting to mysql and returns data that was loaded. I cannot see what is missing WRT configuration:
Testcase:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {QueueServiceApplication.class, TestConfig.class})
#WebAppConfiguration
#ActiveProfiles({"test"})
public class QueueServiceApplicationTests {
private static final int EXPECTED_SERVER_COUNT = 10;
#Autowired
private WebApplicationContext webCtx;
private MockMvc mvc;
#Before
public void init() {
mvc = MockMvcBuilders.webAppContextSetup(webCtx).build();
}
#Test
public void successListAll() throws Exception {
mvc.perform(get("/listall")).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$", hasSize(EXPECTED_SERVER_COUNT)));
}
}
Test configuration object for embedded datasource:
#Configuration
#Profile("test")
public class TestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.addScript("classpath:/db/migration/V1_0001__create_queue_server_table.sql")
.addScript("classpath:/db/migration/V1_0002__queue_server_entries.sql")
.setType(EmbeddedDatabaseType.H2)
.setName("vitel-balancer")
.setScriptEncoding("UTF8")
.build();
}
}
Launcher:
#SpringBootApplication
public class QueueServiceApplication {
public static void main(String[] args) {
SpringApplication.run(QueueServiceApplication.class, args);
}
}
I'm using spring-boot 1.3.2, java 8 update 72
I have been able to address this by changing my TestConfig class
#Configuration
#Profile("test")
public class TestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
#Bean
public ResourceDatabasePopulator populator() {
ResourceDatabasePopulator pop = new ResourceDatabasePopulator();
pop.addScript(new ClassPathResource("db/migration/V1_0001__create_queue_server_table.sql"));
pop.addScript(new ClassPathResource("db/migration/V1_0002__queue_server_entries.sql"));
pop.setContinueOnError(true);
return pop;
}
#Bean
public DataSourceInitializer dbInit(DataSource ds, ResourceDatabasePopulator populator) {
DataSourceInitializer init = new DataSourceInitializer();
init.setDataSource(ds);
init.setDatabasePopulator(populator);
init.setEnabled(true);
return init;
}
}
I'm not sure why this is different that using the EmbeddedDatabaseBuilder and adding the scripts to it. Would be greatful if there is an explaination