I'm trying to get data using #DataProvider, which returns Object[][], in which I'm pasting value by calling another method. This method, in its turn, using #Parameters to get value from XML.
The problem is that I'm getting NullPointerException, because in #DataProvider calling required method with #Parameters by passing value null, hoping that #Parameters will change this value to appropriate one from XML.
At the same time, I cannot call method by not passing any arguments to it.
Code:
Class TestSuite
package blablabla.mainPackage;
import blablabla.framework.*;
import java.io.IOException;
import java.util.ArrayList;
import org.testng.annotations.Test;
public class TestSuite extends Config {
FilesOperations fOps = new FilesOperations();
List<String> fileNames = new ArrayList<String>();
#Test(groups = {"positive"},
dataProvider = "getRandomFileName",
priority = 1)
public void createFileRandom(String fileName) throws IOException {
fOps.createFile(fileName, tempPath);
fileNames.add(fileName);
}
}
Class Config
package blablabla.mainPackage;
import blablabla.framework.*;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Parameters;
public class Config extends DataProviders{
public static Path tempPath;
DirectoriesOperations dirOps = new DirectoriesOperations();
#BeforeSuite(alwaysRun = true)
#Parameters({"path"})
public void tearUp(String path) throws IOException {
tempPath = dirOps.createTempDir(Paths.get(path));
}
#AfterSuite(alwaysRun = true, enabled = true)
public void tearDown() throws IOException {
dirOps.deleteTempDirOnExit(tempPath);
}
}
Class DataProviders
package blablabla.framework;
import java.io.IOException;
import org.testng.annotations.DataProvider;
public class DataProviders {
FilesOperations fOps = new FilesOperations();
HelpFunctions hf = new HelpFunctions();
ParametrizedFunctions pf = new ParametrizedFunctions();
#DataProvider(name = "getRandomFileName")
public Object[][] getRandomFileName() {
return new Object[][]{new Object[]{pf.generateRandomFileNameWithExtension(null)}};
}
}
Class ParametrizedFunctions
package blablabla.framework;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Parameters;
public class ParametrizedFunctions {
FilesOperations fOps = new FilesOperations();
HelpFunctions hf = new HelpFunctions();
#Parameters({"extensionsArray"})
public String generateRandomFileNameWithExtension(String extensionsArray) {
return fOps.getFileName(hf.stringToArray(extensionsArray), null);
}
}
Here, #Parameters({"extensionsArray"}) does't provide a value from XML file. It just takes null, that was passed as an argument for calling method generateRandomFileNameWithExtension(). And, at the same time, I cannot call this method from #DataProvider without passing any argument to method called.
Hope for your suggestions.
I found the solution. The best way to pass parameter from XML into #DataProvider is passing ITestContext context as the argument to the #DataProvider method, and then, get required parameter using:
context.getCurrentXmlTest().getParameter("parameterName");
Full code of #DataProvider:
#DataProvider(name = "getRandomFileName")
public Object[][] getRandomFileName(ITestContext context) {
String extensionsArray = context.getCurrentXmlTest().getParameter("extensionsArray");
return new Object[][]{new Object[]{pf.generateRandomFileNameWithExtension(extensionsArray)}};
}
Thanks all for your suggestions.
Related
i am actually trying to test my caching mechanism . i am using caffine cache.
Test: i am calling caching method twice and expecting the same result for multiple method invocation. i.e When i cal method second time with same signature it shouldn't cal the method it should get the data from cache.
Problem: My code is actually invoking the method twice . i am mocking my repository. Please guide me, if anyone has solved this kind of problem.
my repo :
public class TemplateRepositoryOracle implements TemplateRepository
#Cacheable("Templates")
#Override
public Optional<NotificationTemplate> getNotificationTemplate(String eventTypeId, String destinationType, String destinationSubType) {}
Test:
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Ticker;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class TemplateRepositoyOracleTest {
interface TemplateRepository {
#Cacheable("Templates")
Optional<Template> getNotificationTemplate(String eventTypeId, String destinationType, String destinationSubType);
}
#Configuration
#ConfigurationProperties(prefix = "caching")
#Data
#Slf4j
static class CacheConfiguration {
#Data
public static class CacheSpec {
private Integer expireAfterWrite;
}
private Map<String, CacheSpec> specs;
#Bean
public CacheManager cacheManager(Ticker ticker) {
SimpleCacheManager manager = new SimpleCacheManager();
if (specs != null) {
List<CaffeineCache> caches =
specs.entrySet().stream()
.map(entry -> buildCache(entry.getKey(),
entry.getValue(),
ticker))
.collect(Collectors.toList());
manager.setCaches(caches);
}
return manager;
}
private CaffeineCache buildCache(String name, CacheSpec cacheSpec, Ticker ticker) {
log.info("Cache {} specified timeout of {} min", name, cacheSpec.getExpireAfterWrite());
final Caffeine<Object, Object> caffeineBuilder
= Caffeine.newBuilder()
.expireAfterWrite(cacheSpec.getExpireAfterWrite(), TimeUnit.MINUTES)
.ticker(ticker);
return new CaffeineCache(name, caffeineBuilder.build());
}
#Bean
public Ticker ticker() {
return Ticker.systemTicker();
}
#Bean
TemplateRepository myRepo() {
return Mockito.mock(TemplateRepository.class);
}
}
#Autowired
CacheManager manager;
#Autowired
TemplateRepository repo;
#Test
public void methodInvocationShouldBeCached() {
Optional<Template> third = Optional.of(new NotificationTemplate(UUID.randomUUID(),"Test",DestinationType.SMS,"test","test",Optional.empty(),Optional.empty()));
Optional<Template> fourth = Optional.of(new NotificationTemplate(UUID.randomUUID(),"Test2",DestinationType.SMS,"test2","test2",Optional.empty(),Optional.empty()));
// the mock to return *different* objects for the first and second call
Mockito.when(repo.getNotificationTemplate(Mockito.any(String.class),Mockito.any(String.class),Mockito.any(String.class))).thenReturn(third);
// First invocation returns object returned by the method
Object result = repo.getNotificationTemplate("1","1","1");
assertThat(result, is(third));
// Second invocation should return cached value, *not* second (as set up above)
result = repo.getNotificationTemplate("1","1","1");
assertThat(result, is(third));
// Verify repository method was invoked once
Mockito.verify(repo, Mockito.times(1)).getNotificationTemplate("1","1","1");
assertThat(manager.getCache("notificationTemplates").get(""), is(notNullValue()));
// Third invocation with different key is triggers the second invocation of the repo method
result = repo.getNotificationTemplate("2","2","2");
assertThat(result, is(fourth));
}
}
Property file:
caching:
specs:
Templates:
expireAfterWrite: 1440
For personMap, I am setting the values with Powermockito;
But I am unable to get the values from map;
/**
*
*/
package mapmoocer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PersonStore {
Map<String, java.util.List<Person>> personMap = new HashMap<String, List<Person>>();
public void check() {
List<Person> list = personMap.get("RAM");
for(Person person : list) {
System.out.println(person);
}
}
public void hello() {
System.out.println("Hello");
}
}
Here, is the test class;
for test_check(), not able to cover for each block;
when(personMap.get("RAM")).thenReturn(value); always returning empty; even though I am setting the values for map;
/**
*
*/
package mapmoocer;
import static org.powermock.api.mockito.PowerMockito.when;
import java.util.ArrayList;
import java.util.Map;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.testng.PowerMockObjectFactory;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
public class PersonTest {
#InjectMocks
PersonStore personStore = new PersonStore();
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
#Mock
Map<String, java.util.List<Person>> personMap;
#BeforeClass
public void before(){
MockitoAnnotations.initMocks(this);
}
public void after() {
}
#Test
public void test_hello() {
personStore.hello();
}
#Test
public void test_check() {
Person person = new Person();
person.setEmail("aa");
java.util.List<Person> value = new ArrayList<Person>();
when(personMap.get("RAM")).thenReturn(value);
personStore.check();
}
}
Help me on this.
Why you want to mock a map? you can just create a new Map and assign it to your object. When we say Mock we Mock the action not the data.
We provide a mock is to make sure that the object we use will always provide a consistent value when we call one of its methods.
This will make us focus on the code we test, and don't need to worry about the method your code rely on will give you the wrong result.
So if you use a Map in your code, you just put the data in to the map, it's done. You don't need to mock it at all.
I am able to cover for-each snippet with the following code:
package mapmoocer;
import static org.powermock.api.mockito.PowerMockito.when;
import java.util.ArrayList;
import java.util.Map;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.testng.PowerMockObjectFactory;
import org.testng.Assert;
import org.testng.IObjectFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
public class PersonTest {
#InjectMocks
PersonStore personStore = new PersonStore();
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
#Mock
Map<String, java.util.List<Person>> personMap;
#BeforeClass
public void before(){
MockitoAnnotations.initMocks(this);
}
#AfterClass
public void after() {
}
#Test
public void test_hello() {
personStore.hello();
}
#Test(dataProvider="store")
public void test_check(Object data) {
java.util.List<Person> persons = (java.util.List<Person>)data;
when(personMap.get("RAM")).thenReturn(persons);
personStore.check();
}
public Object[][] store() {
Person person = new Person();
person.setEmail("aa");
person.setName("AA");
java.util.List<Person> value = new ArrayList<Person>();
value.add(person);
Object[][] result = {
{value}
};
return result;
}
}
I have 2 classes which extend PTransform, called CompositeCall2 and CompositeCall.
I have to call CompositeCall first and then, after completion of the work done in CompositeCall, I have to call CompositeCall2 in my dataflow program. I am making template of my dataflow job so parallel processing is going on which makes my work difficult.
Code.:Tester.java
package Testing2;
import java.util.List;
import org.apache.beam.runners.dataflow.DataflowRunner;
import org.apache.beam.runners.dataflow.options.DataflowPipelineOptions;
import org.apache.beam.runners.direct.DirectRunner;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.io.TextIO;
import org.apache.beam.sdk.options.Description;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.options.Validation;
import org.apache.beam.sdk.options.ValueProvider;
import org.apache.beam.sdk.transforms.Create;
import org.apache.beam.sdk.transforms.View;
import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.values.PCollectionView;
import org.apache.beam.sdk.values.PDone;
import com.google.api.services.bigquery.model.TableRow;
public class Tester {
public interface FileData extends PipelineOptions {
#Description("name Of the File")
#Validation.Required
ValueProvider<String> getInputFile();
void setInputFile(ValueProvider<String> value);
#Description("Path Of File From Where We need To Read Data")
#Validation.Required
ValueProvider<String> getOutputFile();
void setOutputFile(ValueProvider<String> value);
}
public static void main(String[] args) throws InterruptedException {
DataflowPipelineOptions options=PipelineOptionsFactory.as(DataflowPipelineOptions.class);
options.setProject("testing1-180111");
options.setTempLocation("gs://kishan-bucket/staging");
options.setTemplateLocation("gs://kiss-bucket/templates/Test1");
options.setRunner(DataflowRunner.class);
Pipeline p = Pipeline.create(options);
PDone dta = p.begin().apply("Creating File",Create.of("Kishan")).apply(new CompositeCall(p));
p.apply("Creating File",Create.of("Kishan")).apply(new CompositeCall2(p));
p.run().waitUntilFinish();
}
}
This is the way I am calling.
Both classes are doing the same work, just printing data in a file and writing that data.
package Testing2;
import java.util.List;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.io.TextIO;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.PTransform;
import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.values.PCollectionView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CompositeCall2 extends PTransform <PCollection<String>,PCollection<String>> {
private static final long serialVersionUID = 1L;
static Pipeline p;
public CompositeCall2(Pipeline p1) {
this.p = p1;
}
private static final Logger LOG = LoggerFactory.getLogger(CompositeCall2.class);
#Override
public PCollection<String> expand(PCollection<String> input) {
PCollection<String> data;
input.apply(ParDo.of(new testing())).apply(TextIO.write().to("gs://kiss-bucket/test1.txt"));
LOG.info("Enter Second Stage Called");
return input;
}
static class testing extends DoFn<String,String>{
#ProcessElement
public void processElement(ProcessContext c) throws InterruptedException{
LOG.info("Enter Second Stage");
c.output("Data Is"+c.element());
}
}
}
How can I synchronize the flow so that after one transformation another transform runs?
This a bit old but I came across it today and thought I might share for others that are having a similar issue - there is a Wait.on transform allows you to wait for a prior transform to complete before applying a later operation.
I want to cover a logic, that creates files with unit tests. Is it possible to mock File class and to avoid actual file creation?
Mock the constructor, like in this example code. Don't forget to put the class that will invoke the "new File(...)" in the #PrepareForTest
package hello.easymock.constructor;
import java.io.File;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({File.class})
public class ConstructorExampleTest {
#Test
public void testMockFile() throws Exception {
// first, create a mock for File
final File fileMock = EasyMock.createMock(File.class);
EasyMock.expect(fileMock.getAbsolutePath()).andReturn("/my/fake/file/path");
EasyMock.replay(fileMock);
// then return the mocked object if the constructor is invoked
Class<?>[] parameterTypes = new Class[] { String.class };
PowerMock.expectNew(File.class, parameterTypes , EasyMock.isA(String.class)).andReturn(fileMock);
PowerMock.replay(File.class);
// try constructing a real File and check if the mock kicked in
final String mockedFilePath = new File("/real/path/for/file").getAbsolutePath();
Assert.assertEquals("/my/fake/file/path", mockedFilePath);
}
}
try PowerMockito
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
#PrepareForTest(YourUtilityClassWhereFileIsCreated.class)
public class TestClass {
#Test
public void myTestMethod() {
File myFile = PowerMockito.mock(File.class);
PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(myFile);
Mockito.when(myFile.createNewFile()).thenReturn(true);
}
}
I'm not sure if it's possible, but I have had such a requirement, and I solved it by creating a FileService interface. So instead of creating/accessing files directly, you add an abstraction. Then you can easily mock this interface in your tests.
For instance:
public interface FileService {
InputStream openFile(String path);
OutputStream createFile(String path);
}
Then in your class using this:
public class MyClass {
private FileService fileService;
public MyClass(FileService fileService) {
this.fileService = fileService;
}
public void doSomething() {
// Instead of creating file, use file service
OutputStream out = fileService.createFile(myFileName);
}
}
And in your test
#Test
public void testOperationThatCreatesFile() {
MyClass myClass = new MyClass(mockFileService);
// Do your tests
}
This way, you can even mock it without any mock libraries.
I have a DummyResource class and a DummyTarget file, and a test class TestDummyResource as below, but the mocked object DummyResource dr = mock(DummyResource.class) only works when I call the constructor inside a normal class, when it's called in an anonymous class, it's calling the actual constructor instead of using the mocked object.
Versions:
powermock 1.4.12 mockito 1.9.0 junit 4.8.2
DummyTarget.java:
import java.io.IOException;
import java.io.OutputStream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
public class DummyTarget {
public StreamingOutput testMocking() {
return new StreamingOutput() {
#Override
public void write(OutputStream arg0) throws IOException, WebApplicationException {
new DummyResource();
}
};
}
}
DummyResource.java:
package com.smin.dummy;
public class DummyResource {
public DummyResource() {
System.out.println("mock failure");
}
}
TestDummyResource.java:
package com.smin.dummy;
import static org.mockito.Mockito.mock;
import java.io.IOException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({DummyResource.class,DummyTarget.class})
public class TestDummyResource {
#Before
public void setUp() throws Exception {
DummyResource dr = mock(DummyResource.class);
PowerMockito.whenNew(DummyResource.class).withNoArguments().thenReturn(dr);
}
#Test
public void testMocked() throws WebApplicationException, IOException {
new DummyResource(); // it uses the mocked object dr here,
//doesn't print "mock failure"
StreamingOutput sop = new DummyTarget().testMocking();
sop.write(null); // it calls DummyResource's constructor,
// prints ""mock failure"" here
}
}
You need to have prepared the class calling the constructor, not the class on which the constructor is called, the following should fix you up:
#PrepareForTest(DummyTarget.class)
For more information check this page.
It looks like an anonymous class may inherit the package of the class that defines it. Can you try the wildcard form of PrepareForTest?:
#PrepareForTest("com.smin.dummy.*")
If that doesn't work, you could try the shotgun PrepareEverythingForTest Annotation.
Actually, you have to prepare for test the class that makes the constructor call, not the class on which the constructor was called. See https://github.com/jayway/powermock/wiki/MockConstructor.
In your case, you should use #PrepareForTest(DummyTarget.class)
I had the same problem, and resolved it with using whenNew with fully qualified name. The fully qualified name of an inner anonymous class in your case is:
DummyTarget.class + "$1"
so you should create a mock of that class:
DummyResource dr = mock(Class.forName(DummyTarget.class + "$1"));
and it will work for you.
Also, don't forget to prepare the DummyTarget class:
#PrepareForTest(DummyTarget.class)
Hope it helped =]