FluentAssertions - how to exclude comparison of dictionary keys? - key-value

Using Should().BeEquivalentTo() I want to compare 2 objects which contain a series of key-value pairs but to exclude the actual value of the keys because that will vary. So basically I'm only interested in comparing the contents of the Values.
Example:
MyObject { MyDictionary1 { Key, Value } ... MyDictionary2 { Key, Value } }
compared to
ExpecterdObject { ExpectedDictionary1 { Key, Value } ... ExpectedDictionary2 { Key, Value } }
The 2 objects being of the same class with the same structure but with each instance having unique ids as keys.
I already tried
.Excluding(e => e.KayValuePair.Keys)
which doesn't seem to work as I still get errors saying that
Expected member MyDictionary1 to be a collection with 3 item(s). Expected
member MyDictionary1 to contain key X.

If you have an object structure like MyClass, and you want to override how the Dictionary property is compared between two instances of MyClass. Namely that only the Values of the dictionaries are compared.
class MyClass
{
public int Value { get; set; }
public Dictionary<int, string> Dictionary1 { get; set; }
public Dictionary<int, string> Dictionary2 { get; set; }
}
To do that you can use a combination of Using and WhenTypeIs from the documentation.
Here's a complete example for your case, where the dictionaries have the same Values, but the Keys differ.
public void MyTestMethod()
{
var expected = new MyClass
{
Value = 42,
Dictionary1 = new Dictionary<int, string>
{
[1] = "foo",
[2] = "bar"
},
Dictionary2 = new Dictionary<int, string>
{
[3] = "bar",
[4] = "baz"
}
};
var actual = new MyClass
{
Value = 42,
Dictionary1 = new Dictionary<int, string>
{
[5] = "foo",
[6] = "bar",
},
Dictionary2 = new Dictionary<int, string>
{
[7] = "bar",
[8] = "baz",
}
};
actual.Should().BeEquivalentTo(expected, options => options.
Using<Dictionary<int, string>>(ctx => ctx.Subject.Values.Should().BeEquivalentTo(ctx.Expectation.Values))
.WhenTypeIs<Dictionary<int, string>>());
}

For anyone having this issue in recent times, I was encountering this same issue when my company used Dictionaries with unique strings as the key. I was able to resolve it by writing a custom IEquivalencyStep.
public class DictionaryComparer : IEquivalencyStep
{
public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
{
return context.Subject is IDictionary &&
context.Expectation is IDictionary;
}
public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
{
var actual = (IDictionary)context.Subject;
var expected = (IDictionary)context.Expectation;
var actualValues = actual.Values;
var expectedValues = expected.Values;
actualValues.Should().BeEquivalentTo(expectedValues, options => options
// Other exclusions, options, etc.
);
return true;
}
}
And then wherever you are making your FA equivalency check:
actual.Should().BeEquivalentTo(expected, options => options
.Using(new DictionaryComparer())
// Continue with other exclusions, options, etc...
);
After implementing it, all dictionaries within the parent object will be checked via the custom comparer you set up. You can change the CanHandle overload to look for whatever conditions you want and then only return true if they are met. This will cause the object that returned true from the CanHandle method to be evaluated through the Handle() method below it.
NOTE: This works in FluentAssertions 5, but I'm unsure if this changed in version 6.

Related

Flutter: create an Object from Type or String

I want to create an Object from an object type defined in Type or from an object name defined in String. The following example uses a String to hold the object type. But I think this is not that elegant - even with Type, this if block would increase dramatically for a lot of object types...
I didn't find a better solution for this yet. How can I create that object dynamically from the specified object type?
if (model == 'Event') {
data = Event.fromMap(result);
}
else if (model == 'Content') {
data = Content.fromMap(result);
}
else if (...) {
// ...
}
This is other approach.
class Event{
Event.fromMap(_map){
print('This is an event');
print(_map);
}
}
class Content{
Content.fromMap(_map){
print('This is a content');
print(_map);
}
}
Map<String, Function> types = {
'Event' : (_map)=>Event.fromMap(_map),
'Content' : (_map)=>Content.fromMap(_map),
};
void main() {
var a = types['Event']({'test':'success_event'});
print(a.runtimeType);
var b = types['Content']({'test':'success_content'});
print(b.runtimeType);
}
Its a bit more scalable (since only depends on add the class constructor into the map).
The explanation:
class Event{
Event.fromMap(_map){
print('This is an event');
print(_map);
}
}
class Content{
Content.fromMap(_map){
print('This is a content');
print(_map);
}
}
Here we are creating the test classes. nothing important.
Map<String, Function> types = {
'Event' : (_map)=>Event.fromMap(_map),
'Content' : (_map)=>Content.fromMap(_map),
};
Here we are defining a Map. Why? Because it allows us to access some value through some key in constant time. In this case, the keys are the Strings 'Event', 'Content', but also can be types as you wanted. For simplicity, let them be Strings. The values are Function's, in this example only getting as parameter a _map (because the Class constructors in the example require one parameter _map). So, if you need more types, only add the type and the function encapsulating the constructor for that type.
void main() {
var a = types['Event']({'test':'success_event'});
print(a.runtimeType);
var b = types['Content']({'test':'success_content'});
print(b.runtimeType);
}
Finally you can instantiate the classes easily. Only with the type string and passing to the function the values you want (In this example a map with a key 'test').
In your example would be something like:
data = types[model](result);

Under which conditions I should prefer computed properties over stored properties?

I saw this piece of code today, and was wondering why you would not instead use simple static stored properties?
This is the code that I am curious about:
class ApiKeys {
// movie keys
class var HomePage: String { get { return "homepage" } }
class var Id: String { get { return "id" } }
class var Overview: String { get { return "overview" } }
class var PosterPath: String { get { return "poster_path" } }
class var ReleaseDate: String { get { return "release_date" } }
class var Runtime: String { get { return "runtime" } }
class var Tagline: String { get { return "tagline" } }
class var Title: String { get { return "title" } }
class var Rating: String { get { return "vote_average" } }
// query params
class var ApiKey: String { get { return "api_key" } }
class var Query: String { get { return "query" } }
}
And this is how I would have written the same code:
class ApiKeys {
static let homePage = "homepage"
static let id = "id"
static let overview = "overview"
static let posterPath = "poster_path"
static let releaseDate = "release_date"
static let runtime = "runtime"
static let tagline = "tagline"
static let title = "title"
static let rating = "vote_average"
//Query Params
static let ApiKey = "api_key"
static let query = "query"
}
There won't ever be any need to override the variables, so use of static should be okay. Am I missing something? Is there any advantage or reason to use the first method over the second?
For what it's worth, I wouldn't be inclined to use computed or stored properties at all. Rather than defining this to be a class, this seems like a textbook case for an enum:
enum ApiKey: String {
// movie keys
case HomePage = "homepage"
case Id = "id"
case Overview = "overview"
case PosterPath = "poster_path"
case ReleaseDate = "release_date"
case Runtime = "runtime"
case Tagline = "tagline"
case Title = "title"
case Rating = "vote_average"
// query params
case ApiKey = "api_key"
case Query = "query"
}
This more accurately captures the notion that a "key" can be one of those values.
And you'd use it like so:
if key == ApiKey.HomePage.rawValue {
...
}
Or
if ApiKey(rawValue: key) == .HomePage {
...
}
In answer to your original question, “when should I prefer computed properties”, the answer is that you generally use them to retrieve a value computed from other properties and, optionally, if you want to set other (possibly private) properties and values indirectly. There's little benefit to using computed properties if you're just going to return some static, unchanging string.
A class var can be overridden by a subclass while a static constant can't. That's the first difference I can think about.
Computed properties can be used to dynamically change the value of the property at runtime if necessary, just like and overridden getter can in Objective-C. You can't do that with a static let constant.
Possibly somewhat off-topic: but one possibly contrived usage scenario where static stored properties cannot be used is if you define non-blueprinted static computed properties with default implementations in an extension to some "constants" protocol. Classes/structs/etc that conform to such a protocol can be allowed to access type constrained generics, where these generics are the the only context in which the protocol constants are accessible (limit the accessibility to the constants) where they are guaranteed to be constants (since they can also be used directly from the concrete types that conform that protocol, but these can "override" the "constants" with new values).
protocol HasAccessToConstants {
/* since we don't blueprint 'theAnswer', the default
implementation below will always be used for objects
conforming to this protocol when used in a generic
context (even if they attempt to "override" these
"constants" with implementations of their own, these
custom ones can only be accessed for concrete-types). */
}
extension HasAccessToConstants {
static var theAnswer: Int { return 42 }
/* for protocols: we may implement a default
implementation only for computed properties */
}
class Foo : HasAccessToConstants {
/* Even if the developer implements its own "constant"
implementation, this will not be used for accessing
Foo type in a generic context. */
static var theAnswer: Int { return 9 }
}
func onlyForObjectsWithAccessToConstants<T: HasAccessToConstants>(obj: T) {
// do something with obj ...
// make use of constants available to the type of obj
print("Constants available to the type of this object (e.g. '\(T.theAnswer)')")
}
onlyForObjectsWithAccessToConstants(Foo())
/* Constants available to the type of this object (e.g. '42') */
// not really "constants" as they can be "overridden" for concrete types
print(Foo.theAnswer) // 9 (since concrete type)
Again, contrived, and included for the technical discussion, as I can't really see in what scenario this would be more useful than other, better alternatives.

Macro to fill out field names, values, and switch statements of a custom #:enum abstract?

I have a bit of a unique situation. For various reasons, chiefly interoperating with a nullable stringly typed legacy system, as well as various other needs I won't go into at the moment, I've settled on a custom #:enum abstract that looks like this:
#:enum abstract MyEnum(Null<Int>) {
public var A = 0;
public var B = 1;
public var C = 2;
public var D = 3;
public var E = 4;
public var F = 5;
public var G = 6;
#:from private static function fromString (value:String):MyEnum {
return switch (value) {
case "a": A;
case "b": B;
case "c": C;
case "d": D;
case "e": E;
case "f": F;
case "g": G;
default: null;
}
}
#:to private static function toString (value:Int):String {
return switch (value) {
case A: "a";
case B: "b";
case C: "c";
case D: "d";
case E: "e";
case F: "f";
case G: "g";
default: null;
}
}
}
However, that's an annoyingly large amount of things to type, and when adding and removing members it's easy to make a manual error. Clearly, this follows a super predictable pattern and seems like a great thing to construct with a macro, but I am terrible at haxe macros.
Can someone explain how I could use a macro to build this enum in such a way that all I have to supply is a list of field names?
pseudocode:
#:enum abstract MyEnum = doTheMacroMagic(["A","B","C","D","E","F","G"]);
The logical steps would be:
Declare public vars from field names (upper case)
Declare fromString/toString values from field names (lower case)
Set public vars to 0-based integers and follow same order as field names are supplied
I think a simple practical example like this might make haxe macros finally "click" for me if I can see it in action.
Flixel handles a very similar use case in for classes like FlxKey with FlxMacroUtil.buildMap(). This expression macro looks for all uppercase, inline vars it finds in the abstract and generates a Map<String, EnumType> from it, with the keys being the field names and the values the field values (or the inverse of that if invert is true).
#:enum
abstract FlxKey(Int) from Int to Int
{
public static var fromStringMap(default, null):Map<String, FlxKey>
= FlxMacroUtil.buildMap("flixel.input.keyboard.FlxKey");
public static var toStringMap(default, null):Map<FlxKey, String>
= FlxMacroUtil.buildMap("flixel.input.keyboard.FlxKey", true);
var A = 65;
var B = 66;
// more keys...
#:from
public static inline function fromString(s:String)
{
s = s.toUpperCase();
return fromStringMap.exists(s) ? fromStringMap.get(s) : NONE;
}
#:to
public inline function toString():String
{
return toStringMap.get(this);
}
}
I'd imagine that's a good starting point. If you want to generate the entire abstract, you will need a #:build macro.
Answering the follow-up question, how to generate fields: This is actually quite straightforward with a build macro:
#:enum
#:build(Macro.createVariables(["A", "B", "C", "D", "E"]))
abstract Generated(Int)
{
}
Macro.hx (sensible to have in its own file to avoid having to deal with #if macro conditionals):
package;
import haxe.macro.Context;
import haxe.macro.Expr;
class Macro
{
public static macro function createVariables(varNames:Array<String>):Array<Field>
{
// get the current fields of the calling type (empty array in this case)
var fields = Context.getBuildFields();
for (i in 0...varNames.length)
// create a custom variable and add it to the fields
fields.push(createVariable(varNames[i], i));
return fields;
}
private static function createVariable(name:String, value:Int):Field
{
return {
name: name,
doc: null,
meta: [],
access: [Access.APublic, Access.AStatic, Access.AInline],
kind: FieldType.FVar(macro:Int, macro $v{value}),
pos: Context.currentPos()
}
}
}
You'll notice the fields showing up in auto-completion for Generated.. You can also see what's been generated by looking at the Generated_Impl.dump when doing an AST dump.

How do I implement custom operator [] in swift

I have written a simple queue class in swift. It's implemented by an Array.
Now I want this performs more like built-in array.So I need to implement the []operator but failed. Somebody help?
public class SimpleQueue<T : Any>
{
private var frontCur = 0
private var reuseCur = -1
private var capacity = 0
private var impl = [T]()
public var count : Int
{
get
{
return impl.count - frontCur
}
}
public func empty() -> Bool
{
return self.count == 0
}
public func size() -> Int
{
return impl.count
}
public func append(o : T)
{
if(frontCur > reuseCur && reuseCur >= 0)
{
impl[reuseCur] = o
reuseCur++
}
else
{
impl.append(o)
}
}
public func pop()
{
frontCur++
}
public func front() -> T
{
return impl[frontCur]
}
public postfix func [](index:Int) -> T //Error!!!!
{
return impl[index + frontCur]
}
}
var x = SimpleQueue<Int>()
for index in 1...10{
x.append(index)
}
print(x.count)
for index in 1...3{
x.pop()
}
print(x.count,x.front(),x[2]) // x[2] Error!!!
apple docs
Subscripts enable you to query instances of a type by writing one or
more values in square brackets after the instance name. Their syntax
is similar to both instance method syntax and computed property
syntax. You write subscript definitions with the subscript keyword,
and specify one or more input parameters and a return type, in the
same way as instance methods.
Subscript is not an operator. Just a method marked with the subscript keyword.
subscript (index:Int) -> T {
return impl[index + frontCur]
}
Read this:
class MyColl {
private var someColl : [String] = []
subscript(index: Int) -> String {
get {
return someColl[index]
}
set(value) {
someColl[index] = value
}
}
}
And read this:
Swift has a well-designed and expansive suite of built-in collection types. Beyond Array, Dictionary, and the brand new Set types, the standard library provides slices, lazy collections, repeated sequences, and more, all with a consistent interface and syntax for operations. A group of built-in collection protocols—SequenceType, CollectionType, and several others—act like the steps on a ladder. With each step up, a collection type gains more functionality within the language and the standard library.

Implementing an indexer in a class in TypeScript

Is it currently possible to implement an indexer on a class in TypeScript?
class MyCollection {
[name: string]: MyType;
}
This doesn't compile. I can specify an indexer on an interface, of course, but I need methods on this type as well as the indexer, so an interface won't suffice.
Thanks.
You cannot implement a class with an indexer. You can create an interface, but that interface cannot be implemented by a class. It can be implemented in plain JavaScript, and you can specify functions as well as the indexer on the interface:
class MyType {
constructor(public someVal: string) {
}
}
interface MyCollection {
[name: string]: MyType;
}
var collection: MyCollection = {};
collection['First'] = new MyType('Val');
collection['Second'] = new MyType('Another');
var a = collection['First'];
alert(a.someVal);
This is an old question, for those looking for the answer: now it's possible to define a indexed property like:
let lookup : {[key:string]:AnyType};
the signature of the key must be either string or integer see:
Interfaces on www.typescriptlang.org
Is not possible to define an indexed property getter/setter in a class but you can "simulate" that in a way like this using Proxy:
class IndexedPropSample {
[name: string | symbol]: any;
private static indexedHandler: ProxyHandler<IndexedPropSample> = {
get(target, property) {
return target[property];
},
set(target, property, value): boolean {
target[property] = value;
return true;
}
};
constructor() {
return new Proxy(this, IndexedPropSample.indexedHandler);
}
readIndexedProp = (prop: string | symbol): any => {
return this[prop];
}
}
var test = new IndexedPropSample();
test["propCustom"] = "valueCustom";
console.log(test["propCustom"]); // "valueCustom"
console.log(test.readIndexedProp("propCustom")); // "valueCustom"
console.log(test instanceof IndexedPropSample); // true
console.log(Object.keys(test)); // ["propCustom", "readIndexedProp"]
you can try it in Typescript Playground