I have a program that I want to mock data for using Mockito.
My main program is AdDataAggregate and it calls AdDataConnect.
AdDataConnect makes a call to an API that returns a string that is parsed into JSON and aggregated.
I've created the mocks and they return data but they are not being used by the main program.
Can someone please show me the error of my ways. Thanks in advance for your help.
//Main Program
public class AdDataAggregate {
public List<AdData> processInfo(long[] adIds){
AdDataConnect adDataConnect = new AdDataConnect();
List<AdData> adAccumData = new ArrayList<AdData>();
for (long adId: adIds) {
data = adDataConnect.connectToData(adId); <———— method to Mock.
}
}
}
//Test Program
#RunWith(MockitoJUnitRunner.class)
public class AdDataTest {
#InjectMocks
private AdDataAggregate adDataAggregate = new AdDataAggregate();
#Mock
private AdDataConnect adDataConnect;
private String oneAdId =
"[{\"advertiser_id\":\"1\",\"ymd\":\"2015-12-" +
"07\",\"num_clicks\":10,\"num_impressions\":100}," +
"{\"advertiser_id\":\"1\",\"ymd\":\"2015-12-" +
"06\",\"num_clicks\":20,\"num_impressions\":200}," +
"{\"advertiser_id\":\"1\",\"ymd\":\"2015-12-" +
"05\",\"num_clicks\":30,\"num_impressions\":300}]";
#Test
public void testWithOneAdId(){
MockitoAnnotations.initMocks(this);
adDataConnect = mock(AdDataConnect.class);
adDataAggregate = mock(AdDataAggregate.class);
when(adDataConnect.connectToData(eq(1L)))
.thenReturn(oneAdId);
String myString = adDataConnect.connectToData(1L);
long[] adIds = new long[]{1L};
List<AdData> outData = adDataAggregate.processInfo(adIds);
Assert.assertEquals(1, outData.size());
Assert.assertEquals(myString, oneAdId);
Assert.assertEquals(60, outData.get(0).getNumImpressions());
Assert.assertEquals(600, outData.get(0).getNumImpressions());
}
}
You need to inject the AdDataConnect into your AdDataAggregate instead of instantiating it. When you instantiate it from within AdDataAggregate you are forcing an implementation to be used. You need to allow someone from the outside to set it so that you can set the mocked version in your tests.
Here is how you do it. Pass the AdDataConnect in the constructor:
public class AdDataAggregate
{
private AdDataConnect adDataConnect;
public AdDataAggregate(AdDataConnect adDataConnect)
{
this.adDataConnect = adDataConnect;
}
public List<AdData> processInfo(long[] adIds)
{
List<AdData> adAccumData = new ArrayList<AdData>();
for(long adId : adIds)
{
data = adDataConnect.connectToData(adId);
}
}
}
Then in your test do this. You can see my comment where I used the new constructor:
#RunWith(MockitoJUnitRunner.class)
public class AdDataTest
{
private AdDataAggregate adDataAggregate;
#Mock
private AdDataConnect adDataConnect;
private String oneAdId = "[{\"advertiser_id\":\"1\",\"ymd\":\"2015-12-"
+ "07\",\"num_clicks\":10,\"num_impressions\":100}," + "{\"advertiser_id\":\"1\",\"ymd\":\"2015-12-"
+ "06\",\"num_clicks\":20,\"num_impressions\":200}," + "{\"advertiser_id\":\"1\",\"ymd\":\"2015-12-"
+ "05\",\"num_clicks\":30,\"num_impressions\":300}]";
#Test
public void testWithOneAdId()
{
MockitoAnnotations.initMocks(this);
adDataAggregate = new AdDataAggregate(adDataConnect);//PASS THE MOCK HERE
when(adDataConnect.connectToData(eq(1L))).thenReturn(oneAdId);
String myString = adDataConnect.connectToData(1L);
long[] adIds = new long[] { 1L };
List<AdData> outData = adDataAggregate.processInfo(adIds);
Assert.assertEquals(1, outData.size());
Assert.assertEquals(myString, oneAdId);
Assert.assertEquals(60, outData.get(0).getNumImpressions());
Assert.assertEquals(600, outData.get(0).getNumImpressions());
}
}
Related
I'm working on testing a class. This class calls on a service (let's say its called client, and we want to call client.put())
put() should return a response, but at least in the test, the response is null
I don't know if I just didn't setup the mock correctly and wanted to sanity check with you guys here
public class ATest {
#Mock
private ServiceProto.PutItemsResponse res;
...(private variables)...
#Before
public void setUp() throws Exception {
client = mock(Client.class);
clientFactory = mock(ClientFactory.class);
when(clientFactory.get(any())).thenReturn(client);
...(initializing private vars for constructor as mock variables, example below...)
captionConverter = mock(CaptionToCTItemConverter.class);
when(privateVar.convert(any(obj.class))).thenReturn(Item.newBuilder().build());
classAToTest = spy(new ClassAToTest(private variables);
}
#Test
public void putItem() {
long id = 4710582L;
AObject aObject = testUtils.getObject();
doReturn(res).when(client).putItems(any(ServiceProto.PutItemsRequest.class));
System.out.println("result is "+ res);
try {
classAToTest.putMethod(aObject);
}
catch (NullPointerException e) {
}
verify(creativeToolsClient, Mockito.times(1)).putItems(any(IngestionServiceProto.PutItemsRequest.class));
}
}
And this is the method being tested
public void putMethod(AObject aObject) {
final String id = Long.toString(aObject.getId());
ServiceProto.PutItemsResponse putItemsResponse = null;
Exception putItemsFailure = null;
putItemsResponse =
client.putItems(ServiceProto.PutItemsRequest.newBuilder()
.putItems(
id,
ServiceProto.PutItemsRequest.Item.newBuilder()).build())
.build());
if (putItemsResponse == null) {
logger.warning("PutItems request has failed: "+
(putItemsFailure == null ? "null" : putItemsFailure.getMessage()));
}
}
and when I run it it gives the warning
The putItems method works for other people. Did I set up mock incorrectly?
res variable is not initialized. To mock objects with #Mock annotation use
#ExtendWith(MockitoExtension.class)
public class ATest {
...
Please need to test this method paramsRequired but not as it can reproduce the behavior for testing. How to know if when passing the null parameters the method will skip the if?
My class service
public class TestStack {
private GeoClassService service;
public Address getAddress(String city,String neighborhood, boolean listOut) {
List<GeoLocation> listLocation = new ArrayList<>();
FutureTask<List<GeoLocation>> returnLoc = null;
Address location = new Address();
boolean paramsRequired = city!=null || neighborhood!=null;
if (listOut && paramsRequired) {
returnLoc = new FutureTask<>(() ->
service.getAdrres(city,neighborhood, listOut));
execute.executor(returnLoc);
}
return location;
}
}
my unit test
public class TestStackTests {
#InjectMocks
private TestStack stack;
#Test
public void paramsTest() {
Address paramsRequired = Mockito.spy(stack.getAddress(
"any city", "any", true));
boolean newAddres = paramsRequired==null;
Assert.assertFalse(newAddres);
}
}
I don't think I'm testing anything but honestly, I don't know how to do this test
How to test void methods in Mockito with assertSame or assertEquals. I am able to do verify only.
i am getting sonar or PMD rules violation -"JUnit tests should include assert() or fail()".
Below is my sample class with test class.
#Service
public class MyServiceImpl implements IService {
#Autowired
private IDyDBDAO dyDBDAO;
#Override
public void update() {
dyDBDAO.save(getDetailData());
}
#Override
public List<Detail> getCurrentDetail() {
return getDetails(dyDBDAO.findAll());
}
private List<Detail> getDetails(Iterable<Detail> details) {
...blah...
}
private String getPlace(){
Places p = Places.getPlace();//static
return p == null? PlacesUtil.getName("DH"): p.getName;
}
private Detail getDetailData() {
Detail d = new Detail();
d.setName("blah");
d.setDesc("fsdfsdfdsf");
d.setPlace(getPlace());
return d;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({Places.class, PlacesUtil.class})
public class MyServiceImplTest {
#InjectMocks
private MyServiceImpl myServiceImpl;
#Mock
private IDyDBDAO dyDBDAO;
#Test
public void testGetCurrentDetail() {
given(dyDBDAO.findAll()).willReturn(getMockDetails());
assertSame(myServiceImpl.getCurrentDetail().size(), 2);
}
#Test
public void testUpdate() {
PowerMockito.mockStatic(Places.class);
// first update , second update -us-west-2 will update
given(Places.getPlace()).willReturn(PlacesUtil.getName("UH"))
.willReturn(null);
myServiceImpl.syncStatus();
// update again with DH
myServiceImpl.syncStatus();
verify(dyDBDAO, times(2)).save(any(Detail.class));
// how to assert checking here
}
private Iterable<Detail> getMockDetails() {
Detail d1 = new Detail();
d1.setName("blah");
d1.setDesc("fsdfsdfdsf");
d1.setPlace("sdfsdf");
Detail d2 = new Detail();
d2.setName("blahblah1");
d2.setDesc("e345345");
d2.setPlace("8907j");
List<Detail> listOfDetail = new ArrayList<>();
listOfDetail.add(eps1);
listOfDetail.add(eps2);
return listOfDetail;
}
}
You need to capture the value passed to the dao save method. Use mockito's ArgumentCaptor for that. Then assert on that value.
Something along these lines:
ArgumentCaptor<Detail> captor = ArgumentCaptor.forClass(Detail.class);
verify(dyDBDAO, times(2)).save(captor.capture());
Detail detail1 = captor.getValues().get(0)
assertEquals(expectedDetail, detail1)
I would assume that your void method that needs to be tested is update in MyServiceImpl.
Firstly, you can verify if dyDBDAO.save() is called.
Mockito.verify(dyDBDAO).save(Mockito.anyList...);
Secondly, you can check the modified or created records in the database by retrieving them and comparing to the inputs from getMockDetails.
I am facing an issue wherein I have created a parameterized method that uses dataprovider. Both DataProvider and method and created in same class. Now, I want to call this method from another class but it requires parameters to be passed which I cannot since they are being read from dataProvider.
I have tried declaring the dataProvider in different class too but that doesn't work. Please suggest some workaround for it.
NOTE: I have a restriction that I cannot use TestNG.xml to implement this scenario.
Please find the code below:
DataProvider:
#DataProvider(name = "TestSuite")
public Object[][] dataSheetTraverser() {
String SheetName = "ProgLang";
datatable = new Xls_Reader(TestDataSheetPath_ProgLang);
int rowcount = datatable.getRowCount(SheetName);
Object result[][] = new Object[rowcount - 1][3];
for (int i = 2; i < rowcount + 1; i++) {
result[i - 2][0] = SheetName;
result[i - 2][1] = i;
result[i - 2][2] = datatable.getCellData(SheetName, "caseType", i);
}
return result;
}
Test Method:
#Test(dataProvider="TestSuite_ProgLang",priority =2)
public void TC_Verify_EditProgLang(String SheetName,int i, String caseType)
{
String test1= datatable.getCellData(SheetName, "Skills", i);
String test2= datatable.getCellData(SheetName, "Version", i);
String test3= datatable.getCellData(SheetName, "LastUsed", i);
String test4= datatable.getCellData(SheetName, "ExperienceYr", i);
String ExperienceMn = datatable.getCellData(SheetName, "ExperienceMn", i);
proglang.FillForm_ProgLang(Skills, Version, LastUsed, ExperienceYr, ExperienceMn);
}
I want to call the above function TC_Verify_EditProgLang from another class. Please suggest.
You can use the dataProviderClass attribute for calling from other class
in #Test and The Provider method Must be static :
public class StaticProvider {
#DataProvider(name = "create")
public static Object[][] createData() {
return new Object[][] {
new Object[] { new Integer(42) }
};
}
}
//different Class
public class MyTest {
#Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
public void test(Integer n) {
// ...
}
}
please check the Documentation :dataProviders
I have classes called ctdl_User, ctdl_Device and ctdl_Options.
I have a function that saves ctdl_User objects using the binary formatter, and another that loads them. However the functions specifically expect to take and return User objects, and I want to use this function to load other objects of mine.
How do I go about changing what types the functions will take? Here is the save and load functions...
public ctdl_User Load()
{
ctdl_User loadedUsr = new ctdl_User();
string DataFileSave = Settings.Default.savePath + "\\testuserfile.dat";
FileStream dataStr = new FileStream(DataFileSave, FileMode.Open);
BinaryFormatter frmtr = new BinaryFormatter();
loadedUsr = (ctdl_User) frmtr.Deserialize(dataStr);
dataStr.Close();
return loadedUsr;
}
public static void Save(ctdl_User usr)
{
string DataFileSave = Settings.Default.savePath + "\\testuserfile.dat";
File.Delete(DataFileSave);
FileStream dataStr = new FileStream(DataFileSave, FileMode.Create);
BinaryFormatter frmtr = new BinaryFormatter();
frmtr.Serialize(dataStr, usr);
dataStr.Close();
}
The following demonstrates an approach using generics in C#:
public static T Load<T>() where T : new()
{
T loadedUsr = new T();
string DataFileSave = Settings.Default.savePath + "\\testuserfile.dat";
FileStream dataStr = new FileStream(DataFileSave, FileMode.Open);
BinaryFormatter frmtr = new BinaryFormatter();
loadedUsr = (T) frmtr.Deserialize(dataStr);
dataStr.Close();
return loadedUsr;
}
public static void Save<T>(T usr)
{
string DataFileSave = Settings.Default.savePath + "\\testuserfile.dat";
File.Delete(DataFileSave);
FileStream dataStr = new FileStream(DataFileSave, FileMode.Create);
BinaryFormatter frmtr = new BinaryFormatter();
frmtr.Serialize(dataStr, usr);
dataStr.Close();
}
Note the use of the new() constraint in the Load() method.
Here's an example of calling these methods:
public static void Main(string[] args)
{
ctdl_User user = new ctdl_User();
user.name = "Alice";
Save<ctdl_User>(user);
ctdl_User user2 = Load<ctdl_User>();
Console.WriteLine(user2.name);
ctdl_Device device = new ctdl_Device();
device.type = "printer";
Save<ctdl_Device>(device);
ctdl_Device device2 = Load<ctdl_Device>();
Console.WriteLine(device2.type);
}
For completeness, here are the stub classes I used to test this code:
[Serializable()]
class ctdl_User
{
public string name;
}
[Serializable()]
class ctdl_Device
{
public string type;
}
Edit: added code to Main() that saves and loads a device, as well as a user.
Assuming this is Java you can just overload the method following this scheme:
public static void Load(Type1 obj)
{
//do sth with object of type Type1
}
public static void Load(Type2 obj)
{
//do sth with object of type Type2
}
//...etc
Also if you have common code for it that can be used for objects of another types you can exrtact this code to one methode that treat overloaded methods as facade
private static void doLoad(Object obj)
{
//the common code
}
public static void Load(Type1 obj)
{
doLoad(obj); // or something else...
}
public static void Load(Type2 obj)
{
doLoad(obj); // or something else...
}
//...etc
You can read more about overloading methods in Java here