Iterate List of Object in Kotlin TestCase - unit-testing

I'm using Unit Test using Kotlin and unable to iterate List of Objects in my Test Case, Kindly check my below Coding,
#Test
#WithMockOAuth(siteId = "5698965", subPermissions = [SubPermission.GETD])
fun `get fee zero`() {
val body = """
{
"newMessage": {
"call": true,
"callMessatgeCount": 3,
"discounted": 2,
"NewFees": 4.99,
"Id" : "extra SIM Business"
}
}
""".trimIndent()
this.server.expect(requestTo("${integrationClientProperties.url}/main/0767777777/register/"))
.andRespond(withSuccess(body, MediaType.APPLICATION_JSON_UTF8))
assertThat(service.getValues("0767777777"))
.hasSize(3)
.first()
.hasFieldOrPropertyWithValue("callMessatgeCount", 3)
.hasFieldOrPropertyWithValue("NewFees", BigDecimal.ZERO)
this.server.verify()
}
Above i can able to check hasFieldOrPropertyWithValue for the first() element, As hasSize(3) i need to check all the 3 values which is List of Objects in the same TestCase method.
List of objects as Below
ListValue:[
{
"newMessage": {
"call": true,
"callMessatgeCount": 3,
"discounted": 2,
"NewFees": 4.99,
"Id" : "extra SIM Business"
},
{
"newMessage": {
"call": true,
"callMessatgeCount": 3,
"discounted": 2,
"NewFees": 0,
"Id" : "extra SIM Business"
},
{
"newMessage": {
"call": true,
"callMessatgeCount": 3,
"discounted": 2,
"NewFees": 4.99,
"Id" : "extra SIM Business"
}
]
Note: I tried element(index) to check the list of objects using multiple test cases.
Updated
Library" org.assertj.core.api.Assertions and supports java8

Assuming you are using AssertJ from the method names and that you have a Java-8-supporting version (i.e. 3.5+), you can find the allSatisfy method:
Verifies that all the elements satisfy given requirements expressed as a Consumer.
This is useful to perform a group of assertions on elements.
From the docs, something like the following should work
assertThat(service.getValues("0767777777"))
.hasSize(3)
.allMatch { assertThat(it)
.hasFieldOrPropertyWithValue("callMessatgeCount", 3)
.hasFieldOrPropertyWithValue("NewFees", BigDecimal.ZERO)
}
You could look into Kotlin-specific libraries as well (especially if you need to compile to JVM 6).

Related

Is there a way in c++ using nlohmann/json to test json for the presence of key without listing each one separately? And if so, how?

I have an application that is split into a backend and a desktop app. The exchange between them takes place by sending requests in json format and everything functions normally until the backend changes are made concerning the object model itself (for json, a specific key is added or removed).
Here is an example of one of the models (from the desktop app side):
void from_json(const nlohmann::json &json, CaseModel &model)
{
from_json(json, (BasicModel&)model);
crm::json_extract(model.office, json.at("office"));
crm::json_extract(model.cid, json.at("cid"));
crm::json_extract(model.commentary, json.at("commentary"));
crm::json_extract(model.date_received, json.at("date_received"));
crm::json_extract(model.purchases, json.at("purchases"));
crm::json_extract(model.purchases, json.at("payments"));
crm::json_extract(model.researches, json.at("researches"));
crm::json_extract(model.participants, json.at("participants"));
crm::json_extract(model.departments, json.at("related_departments"));
crm::json_extract(model.experts, json.at("related_experts"));
crm::json_extract(model.managers, json.at("related_managers"));
crm::json_extract(model.lawyers, json.at("related_lawyers"));
crm::json_extract(model.collectors, json.at("related_collectors"));
crm::json_extract(model.courriers, json.at("related_courriers"));
crm::json_extract(model.attachments, json.at("attachments"));
crm::json_extract(model.resolution, json.at("resolution"));
}
void to_json(nlohmann::json &json, const CaseModel &model)
{
to_json(json, (const BasicModel&)model);
json["office"] = crm::json_dump(model.office);
json["cid"] = crm::json_dump(model.cid);
json["commentary"] = crm::json_dump(model.commentary);
json["date_received"] = crm::json_dump(model.date_received);
json["purchases"] = crm::json_dump(model.purchases);
json["researches"] = crm::json_dump(model.researches);
json["payments"] = crm::json_dump(model.payments);
json["participants"] = crm::json_dump(model.participants);
json["related_departments"] = crm::json_dump(model.departments);
json["related_experts"] = crm::json_dump(model.experts);
json["related_managers"] = crm::json_dump(model.managers);
json["related_lawyers"] = crm::json_dump(model.lawyers);
json["related_collectors"] = crm::json_dump(model.collectors);
json["related_courriers"] = crm::json_dump(model.courriers);
json["attachments"] = crm::json_dump(model.attachments);
json["resolution"] = crm::json_dump((long int)model.resolution);
}
Here's json itself:
{
"result": [
{
"related_departments": [],
"related_experts": [],
"related_managers": [],
"related_lawyers": [],
"related_courriers": [],
"related_collectors": [],
"courtcase": null,
"contractcase": null,
"arbitragecase": null,
"id": 13,
"resolution": 1,
"date_sent_lawyer": null,
"office": 1,
"cid": "test case cid",
"commentary": "",
"date_received": "2021-11-08T12:20:39.337Z",
"purchases": [],
"researches": [],
"participants": [],
"attachments": [],
"payments": [
{
"pk": 1
}
]
}
]
}
Here is a unit test:
#include <gtest/gtest.h>
#include <nlohmann/json.hpp>
#include <glibmm/datetime.h>
#include <glibmm/ustring.h>
#include "Utility/Concepts.hpp"
#include "Database/Models/CaseModel.hpp"
#include "CaseModel_test.hpp"
template<typename T>
concept HasNeededProperties = requires(T model) {
typename T::Property;
T::Property::id;
Glib::ustring(T::Property::id);
T::Property::office;
Glib::ustring(T::Property::office);
T::Property::cid;
Glib::ustring(T::Property::cid);
T::Property::commentary;
Glib::ustring(T::Property::commentary);
T::Property::date_received;
Glib::ustring(T::Property::date_received);
T::Property::purchases;
Glib::ustring(T::Property::purchases);
T::Property::researches;
Glib::ustring(T::Property::researches);
T::Property::participants;
Glib::ustring(T::Property::participants);
T::Property::departments;
Glib::ustring(T::Property::departments);
T::Property::experts;
Glib::ustring(T::Property::experts);
T::Property::managers;
Glib::ustring(T::Property::managers);
T::Property::lawyers;
Glib::ustring(T::Property::lawyers);
T::Property::collectors;
Glib::ustring(T::Property::collectors);
T::Property::courriers;
Glib::ustring(T::Property::courriers);
T::Property::attachments;
Glib::ustring(T::Property::attachments);
T::Property::payments;
Glib::ustring(T::Property::payments);
T::Property::resolution;
Glib::ustring(T::Property::resolution);
T::Property::date_send_lawyer;
Glib::ustring(T::Property::date_send_lawyer);
};
TEST(CaseModelConformity, Concept) {
ASSERT_TRUE(IsDatabaseModel<CaseModel>) << "Doesn't conform to database model description.";
ASSERT_TRUE(HasModelDbTable<CaseModel>) << "Doesn't have an associated database table.";
ASSERT_TRUE(HasCaseFields<CaseModel>) << "Doesn't have some required fields.";
}
TEST(CaseModelConformity, Properties) {
ASSERT_TRUE(HasNeededProperties<CaseModel>) << "Some required properties are missing.";
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::id), "id");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::office), "office");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::cid), "cid");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::commentary), "commentary");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::date_received), "date_received");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::purchases), "purchases");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::participants), "participants");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::researches), "researches");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::departments), "related_departments");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::experts), "related_experts");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::managers), "related_managers");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::lawyers), "related_lawyers");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::collectors), "related_collectors");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::courriers), "related_courriers");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::attachments), "attachments");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::payments), "payments");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::resolution), "resolution");
EXPECT_EQ(static_cast<Glib::ustring>(CaseModel::Property::date_send_lawyer), "date_send_lawyer");
}
TEST(CaseModelConformity, JsonConversion)
{
ASSERT_TRUE(IsJsonConvertible<CaseModel>);
}
There are too many such object models, each has its own json keys and for each registering the key separately to check for availability - not only will kill a lot of time, but it is also pointless, because all of this can be written into working code. But unfortunately, it is not always possible to identify the change and find out where the key mismatch occurred, as a result of which the backend does not accept json.
Ideally, it would be an option to simply compare the two lists of keys with each other, to identify similarities and differences, but I have very little idea of ​​this, and is it even possible to do it?
Does nlohmann have a method for comparing two lists, not listing each element of this list separately, but passing an object?

Projecting over a find query with $elemMatch in mongoDB with the C++ driver

I'm trying to apply a projection using $elemMatch with the mongoDB C++ driver (2.6compat):
Sample document:
{
"name" : "Tom",
"lists" : [
{"value" : 1}, {"value" : 2}, {"value" : 3}
]
}
I would like to get a document for Tom and ONLY value 1.
In the shell this will look like this:
> db.aaa.find({"name" : "Tom", "lists.value" : 1}, {"lists" : {$elemMatch : {"value" : 1} } })
Now, there's no suitable override over the query method which accepts a BSONObj for the projection part of the query. Am I missing something here?
Help will be much appreciated!
you are going to want to use the DBClientBase::query() method. It has this signature:
auto_ptr<DBClientCursor> DBClientBase::query(
const string &ns,
Query query,
int nToReturn,
int nToSkip,
const BSONObj *fieldsToReturn,
int queryOptions,
int batchSize
)
In the 2.6 compatible C++ driver there are no database or collection classes so you need to provide:
the namespace to query (ns)
the query itself (query)
the number of documents to return,
the number to skip (pass zero for default values)
the fieldsToReturn (a BSONObj representing the fields you would want back from the database.
So, for example, if you wanted to do the same thing as above you would write the query like this:
DBClientConnection conn;
conn.connect("localhost:27017");
BSONOBj projection = fromjson("{ lists: {\"$elemMatch:\": {value: 1} } }");
conn.query("db.aaa", Query("{}"), 0, 0, &projection)

Mongodb - regex match of keys for subdocuments

I have some documents saved in a collection (called urls) that look like this:
{
payload:{
url_google.com:{
url:'google.com',
text:'search'
}
}
},
{
payload:{
url_t.co:{
url:'t.co',
text:'url shortener'
}
}
},
{
payload:{
url_facebook.com:{
url:'facebook.com',
text:'social network'
}
}
}
Using the mongo CLI, is it possible to look for subdocuments of payload that match /^url_/? And, if that's possible, would it also be possible to query on the match's subdocuments (for example, make sure text exists)?
I was thinking something like this:
db.urls.find({"payload":{"$regex":/^url_/}}).count();
But that's returning 0 results.
Any help or suggestions would be great.
Thanks,
Matt
It's not possible to query against document keys in this way. You can search for exact matches using $exists, but you cannot find key names that match a pattern.
I assume (perhaps incorrectly) that you're trying to find documents which have a URL sub-document, and that not all documents will have this? Why not push that type information down a level, something like:
{
payload: {
type: "url",
url: "Facebook.com",
...
}
}
Then you could query like:
db.foo.find({"payload.type": "url", ...})
I would also be remiss if I did not note that you shouldn't use dots (.) is key names in MongoDB. In some cases it's possible to create documents like this, but it will cause great confusions as you attempt to query into embedded documents (where Mongo uses dot as a "path separator" so to speak).
You can do it but you need to use aggregation: Aggregation is pipeline where each stage is applied to each document. You have a wide range of stages to perform various tasks.
I wrote an aggregate pipeline for this specific problem. If you don't need the count but the documents itself you might want to have a look at the $replaceRoot stage.
EDIT: This works only from Mongo v3.4.4 onwards (thanks for the hint #hwase0ng)
db.getCollection('urls').aggregate([
{
// creating a nested array with keys and values
// of the payload subdocument.
// all other fields of the original document
// are removed and only the filed arrayofkeyvalue persists
"$project": {
"arrayofkeyvalue": {
"$objectToArray": "$$ROOT.payload"
}
}
},
{
"$project": {
// extract only the keys of the array
"urlKeys": "$arrayofkeyvalue.k"
}
},
{
// merge all documents
"$group": {
// _id is mandatory and can be set
// in our case to any value
"_id": 1,
// create one big (unfortunately double
// nested) array with the keys
"urls": {
"$push": "$urlKeys"
}
}
},
{
// "explode" the array and create
// one document for each entry
"$unwind": "$urls"
},
{
// "explode" again as the arry
// is nested twice ...
"$unwind": "$urls"
},
{
// now "query" the documents
// with your regex
"$match": {
"urls": {
"$regex": /url_/
}
}
},
{
// finally count the number of
// matched documents
"$count": "count"
}
])

Disabling a validation constraint in grails command object for unit testing (with Spock)

I'm trying to write some unit tests for Command object validations.
When my command object has many fields with many validation rules, setting up the command object for each test case gets too verbose and repetitive.
Say I have this command object:
class MemberCommand {
String title
String name
String phone
static constraints = {
title(blank: false, inList: ["Mr", "Mrs", "Miss", "Ms"])
name(blank: false, maxSize:25)
phone(blank: false, matches: /\d{8}/)
}
}
I want to test this by doing something like this:
class ValidationTitle extends UnitSpec {
def "title must be one of Mr, Mrs, Miss, Ms"() {
setup:
def memberCommand = new MemberCommand()
// I don't want to do:
// memberCommand.name = "Spock"
// memberCommand.phone = "99998888"
// Instead, I want to disable other constraints, except the one for title
mockForConstraintsTests MemberCommand, [memberCommand]
when:
memberCommand.title = t
then:
memberCommand.validate() == result
where:
t << ["Mr", "Mrs", "Miss", "Ms", "Dr", ""]
result << [true, true, true, true, false, false]
}
}
This test will fail because when memberCommand.validate() is called, all constraints will be used, and result in validation error even in the case when the title, "Mr" is being tested.
I could set the name and phone for this one test, but then, I'll need to set title and phone when I'm testing for name validation, and title and name when testing for phone validation. You can imagine how this gets more annoying when there are more fields to the command objects with more complicated rules.
Is there any way of disabling constraints in unit testing (with Spock) in grails?
If not, any other suggestions for situations like this?
Thank you.
You can't disable specific constraint validations. But, you can either provide valid values for the rest of your attributes, or check for errors in the title attribute in particular.
In the first case, you simply create a map with default (and valid) attributes and initialize your command from them:
def validAttributes = [ title: 'Mr', name: 'Spock', phone: '99998888' ]
def "title must be one of Mr, Mrs, Miss, Ms"() {
setup:
def memberCommand = new MemberCommand(validAttributes)
mockForConstraintsTests MemberCommand, [memberCommand]
when:
memberCommand.title = t
then:
memberCommand.validate() == result
where:
t << ["Mr", "Mrs", "Miss", "Ms", "Dr", ""]
result << [true, true, true, true, false, false]
}
It's also good practice to have a "baseline" case that validates (I always follow this pattern in my tests). It expresses your basic assumptions about your validations.
For the other possibility, you'd do:
def "title must be one of Mr, Mrs, Miss, Ms"() {
setup:
def memberCommand = new MemberCommand()
mockForConstraintsTests MemberCommand, [memberCommand]
when:
memberCommand.title = t
memberCommand.validate()
then:
memberCommand.errors['title'] == result
where:
t << ["Mr", "Mrs", "Miss", "Ms", "Dr", ""]
result << [null, null, null, null, 'not.inList', 'not.inList']
}
It's possible to test for only the attributes you want by passing an array as argument with their name as Strings:
then:
memberCommand.validate(['title']) == result

Can Googletest value-parameterized with multiple, different types of parameters match mbUnit flexibility?

I'd like to write C++ Google tests which can use value-parameterized tests with multiple parameters of different data types, ideally matching the complexity of the following mbUnit tests written in C++/CLI.
For an explanation of mbUnit, see the Hanselman 2006 article. As of this 2019 edit, the other links he includes are dead.
Note how compact this is, with the [Test] attribute indicating this is a test method and the [Row(...)] attributes defining the values for an instantiation.
[Test]
[Row("Empty.mdb", "select count(*) from collar", 0)]
[Row("SomeCollars.mdb", "select count(*) from collar", 17)]
[Row("SomeCollars.mdb", "select count(*) from collar where max_depth=100", 4)]
void CountViaDirectSQLCommand(String^ dbname, String^ command, int numRecs)
{
String^ dbFilePath = testDBFullPath(dbname);
{
StAnsi fpath(dbFilePath);
StGdbConnection db( fpath );
db->Connect(fpath);
int result = db->ExecuteSQLReturningScalar(StAnsi(command));
Assert::AreEqual(numRecs, result);
}
}
Or even better, this more exotic testing from C# (pushing the boundaries of what can be defined in .Net attributes beyond what's possible in C++/CLI):
[Test]
[Row("SomeCollars.mdb", "update collar set x=0.003 where hole_id='WD004'", "WD004",
new string[] { "x", "y" },
new double[] { 0.003, 7362.082 })] // y value unchanged
[Row("SomeCollars.mdb", "update collar set x=1724.8, y=6000 where hole_id='WD004'", "WD004",
new string[] { "x", "y" },
new double[] { 1724.8, 6000.0 })]
public void UpdateSingleRowByKey(string dbname, string command, string idValue, string[] fields, double[] values)
{
...
}
The help says Value-parameterized tests will let you write your test only once and then easily instantiate and run it with an arbitrary number of parameter values. but I'm fairly certain that is referring to the number of test cases.
Even without varying the data types, it seems to me that a parameterized test can only take one parameter?
2019 update
Added because I got pinged about this question. The Row attribute shown is part of mbUnit.
For an explanation of mbUnit, see the Hanselman 2006 article. As of this 2019 edit, the other links he includes are dead.
In the C# world, NUnit added parameterised testing in a more powerful and flexible way including a way to handle generics as Parameterised Fixtures.
The following test will be executed fifteen times, three times for each value of x, each combined with 5 random doubles from -1.0 to +1.0.
[Test]
public void MyTest(
[Values(1, 2, 3)] int x,
[Random(-1.0, 1.0, 5)] double d)
{
...
}
The following test fixture would be instantiated by NUnit three times, passing in each set of arguments to the appropriate constructor. Note that there are three different constructors, matching the data types provided as arguments.
[TestFixture("hello", "hello", "goodbye")]
[TestFixture("zip", "zip")]
[TestFixture(42, 42, 99)]
public class ParameterizedTestFixture
{
private string eq1;
private string eq2;
private string neq;
public ParameterizedTestFixture(string eq1, string eq2, string neq)
{
this.eq1 = eq1;
this.eq2 = eq2;
this.neq = neq;
}
public ParameterizedTestFixture(string eq1, string eq2)
: this(eq1, eq2, null) { }
public ParameterizedTestFixture(int eq1, int eq2, int neq)
{
this.eq1 = eq1.ToString();
this.eq2 = eq2.ToString();
this.neq = neq.ToString();
}
[Test]
public void TestEquality()
{
Assert.AreEqual(eq1, eq2);
if (eq1 != null && eq2 != null)
Assert.AreEqual(eq1.GetHashCode(), eq2.GetHashCode());
}
[Test]
public void TestInequality()
{
Assert.AreNotEqual(eq1, neq);
if (eq1 != null && neq != null)
Assert.AreNotEqual(eq1.GetHashCode(), neq.GetHashCode());
}
}
Yes, there's a single parameter. You can make that parameter be arbitrarily complex, though. You could adapting the code from the documentation to use you Row type, for example:
class AndyTest : public ::testing::TestWithParam<Row> {
// You can implement all the usual fixture class members here.
// To access the test parameter, call GetParam() from class
// TestWithParam<T>.
};
Then define your parameterized test:
TEST_P(AndyTest, CountViaDirectSQLCommand)
{
// Call GetParam() here to get the Row values
Row const& p = GetParam();
std::string dbFilePath = testDBFullPath(p.dbname);
{
StAnsi fpath(dbFilePath);
StGdbConnection db(p.fpath);
db.Connect(p.fpath);
int result = db.ExecuteSQLReturningScalar(StAnsi(p.command));
EXPECT_EQ(p.numRecs, result);
}
}
Finally, instantiate it:
INSTANTIATE_TEST_CASE_P(InstantiationName, AndyTest, ::testing::Values(
Row("Empty.mdb", "select count(*) from collar", 0),
Row("SomeCollars.mdb", "select count(*) from collar", 17),
Row("SomeCollars.mdb", "select count(*) from collar where max_depth=100", 4)
));
An alternative to using a custom structure as the parameter is to use the parameter generator ::testing::Combine(g1, g2, ..., gn). This generator allows you to combine the other parameter generators into a set of parameters with a type std::tuple that has a template type that matches the types of the values provided.
Note that this generator produces the Cartesian product of the values provided. That means that every possible ordered tuple will be created. I believe the original question is asking for a strict array of parameters with the provided values, which this does not support. If you need to have an array of strict parameters, you could use a tuple with the parameter generator ::testing::Values(v1, v2, ..., vN) where each value is a separate tuple.
Example:
#include <string>
#include <tuple>
class MyTestSuite :
public testing::TestWithParam<std::tuple<std::string, std::string, int>>
{
};
TEST_P(MyTestSuite, TestThatThing)
{
functionUnderTest(std::get<0>(GetParam()),
std::get<1>(GetParam()),
std::get<2>(GetParam()));
. . .
}
INSTANTIATE_TEST_SUITE_P(
MyTestGroup,
MyTestSuite,
::testing::Combine(
::testing::Values("FirstString1", "FirstString2"),
::testing::Values("SecondString1", "SecondString2"),
::testing::Range(10, 13)));
INSTANTIATE_TEST_SUITE_P(
MyOtherTestGroupThatUsesStrictParameters,
MyTestSuite,
::testing::Values(
{"FirstString1", "SecondString1", 10},
{"FirstString2", "SecondString2", 32},
{"FirstString3", "SecondString3", 75}));
In the above example, the parameters created for MyTestGroup would look like the following:
[
{"FirstString1", "SecondString1", 10},
{"FirstString1", "SecondString1", 11},
{"FirstString1", "SecondString1", 12},
{"FirstString1", "SecondString2", 10},
{"FirstString1", "SecondString2", 11},
{"FirstString1", "SecondString2", 12},
{"FirstString2", "SecondString1", 10},
{"FirstString2", "SecondString1", 11},
{"FirstString2", "SecondString1", 12},
{"FirstString2", "SecondString2", 10},
{"FirstString2", "SecondString2", 11},
{"FirstString2", "SecondString2", 12}
]
Refer to the GoogleTest documentation for further details. (Accessed on 12/17/2019)