How to create a TwinCollection with IDictionary<string, object> for GeoPoint property for Azure IoT Hub? - azure-iot-hub

I have an IoT Device with a property that is a Geopoint.
I am using the Azure IoT C# sdk using the following GitHub examples:
azure-iot-samples-csharp
I have code calling the public static TwinCollection CreatePropertyPatch(IDictionary<string, object> propertyPairs) method.
I know the format of the JSON needs to be:
{
"DeviceLocation": {
"lat": 47.64263,
"lon": -122.13035,
"alt": 0
}
}
Is there a way to do this with IDictionary<string, object>??
If so what would the c# sample code look like?

The PnpConvention class that you're referring to doesn't do a lot more than serialize the object you give it. So here's a few things you can do to update the device twin.
You can do it through an anonymous object:
var location = new { lat = 47.64263, lon = -122.13035, alt = 0 };
TwinCollection twinCollection = PnpConvention.CreatePropertyPatch("DeviceLocation", location);
await client.UpdateReportedPropertiesAsync(twinCollection);
Or create a class for this object:
public class DeviceLocation
{
[JsonProperty("lat")]
public double Latitude { get; set; }
[JsonProperty("lon")]
public double Longitude { get; set; }
[JsonProperty("alt")]
public double Altitude { get; set; }
}
var location = new DeviceLocation { Latitude = 47.64263, Longitude = -122.13035, Altitude = 0 };
TwinCollection twinCollection = PnpConvention.CreatePropertyPatch("DeviceLocation", location);
await client.UpdateReportedPropertiesAsync(twinCollection);
Or, my favourite, because the PnpConvention class doesn't do much for device twin updates:
TwinCollection twinCollection = new TwinCollection();
twinCollection["DeviceLocation"] = new { lat = 47.64263, lon = -122.13035, alt = 0 };
await client.UpdateReportedPropertiesAsync(twinCollection);

Related

Xunit Parameterize Selenium By Type

I have asked several basic questions related to this in the past and got great answers that explained several issues. I think i'm now in a position to ask the correct question now that I'm more aware of how Xunit works!
I am trying to parametrize several tests in C# using visual studio. I need each parameter to be displayed as an individual test that can be ran in isolation if required (I know there is a test collection runner and a separate test runner). The test collection runner is my issue.
I know that Xunit requires the parameters to be serialized in order for them to be picked up by the test collection runner. I also know that it by default can easily serialize basic data types like string, bool, int etc.
I have tried various approaches to do this with mixed results. My issue is trying to parameterize the Selenium type 'By'. I can't seem to be able to serialize this. I've tried to trick Xunit for example by using a dictionary List<string, By> and trying to serialize the in the dictionary (no luck!)
Here is the cleanest code I have come across that is simple and elegant for what i'm trying to do, but again I can't serialize the 'By' type. I have played around with changing the static property from bool to By and it returns only 1 test for all params, so it's not being serialized
public class ParamTest1
{
static string test3 = "TestXYZ";
public static TheoryData<int, bool, string, string> DataForTest1 = new TheoryData<int, bool, string, string>
{
{ 1, true, "First", test3 },
{ 2, false, "Second", test3},
{ 3, true, "Third", test3}
};
[Theory(DisplayName = "My First Test"), MemberData(nameof(DataForTest1))]
public void Test1(int valA, bool valB, string valC, string valD)
{
Assert.True(valB);
}
}
Which gives me
I am aware this particular code isn't invoking the IXunitSerializable
So here is an another working example of what I need but I just can't get it to work with the 'By' Type
public class ValidateTestCase : IXunitSerializable
{
public Guid Coupon { get; set; }
public bool IsValid { get; set; }
public void Serialize(IXunitSerializationInfo info)
{
info.AddValue(nameof(Coupon), Coupon.ToString());
}
public void Deserialize(IXunitSerializationInfo info) { }
}
public class Testing
{
public static IEnumerable<object[]> ValidateTestCases
{
get
{
yield return new object[] { new ValidateTestCase { Coupon = Guid.Parse("73e4d185-70cf-4ce4-bc3f-187b7a40e167"), IsValid = false } };
yield return new object[] { new ValidateTestCase { Coupon = Guid.Parse("93b983fb-5b6a-4845-a769-db41900b7df9"), IsValid = false } };
yield return new object[] { new ValidateTestCase { Coupon = Guid.Parse("99c03283-33cb-4e56-a010-c2bc0758ad27"), IsValid = false } };
yield return new object[] { new ValidateTestCase { Coupon = Guid.Parse("16a7fe80-3111-44b0-9ebf-c7159bea637d"), IsValid = false } };
yield return new object[] { new ValidateTestCase { Coupon = Guid.Parse("8b38b4aa-d70f-4ce7-8992-8a60936c5c58"), IsValid = false } };
yield return new object[] { new ValidateTestCase { Coupon = Guid.Parse("abc60aa0-a33b-4057-8f99-5cdceda35c70"), IsValid = true } };
}
}
[Theory(DisplayName = "CouponService should validate coupons")]
[MemberData(nameof(ValidateTestCases))]
public void MyCouponService_Validates(ValidateTestCase vtc)
{
Assert.Equal(vtc.IsValid, true);
}
}
And finally for anyone wondering what the 'By' type is I am referring to it's :
[![enter image description here][2]][2]
Here it is in the debugger so you can see what's going on inside:
[![enter image description here][3]][3]
I know there's a lot going on in there but if anyone has any ideas or suggestions it would be great!
To summarize, I can't parameterize the Selenium 'data type' By.
[2]: https://i.stack.imgur.com/XcLcn.png
[3]: https://i.stack.imgur.com/T9so1.png
Serializing Class
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using OpenQA.Selenium;
using Xunit.Abstractions;
namespace XUnitTestProject1
{
public class ParameterizedHook
{
public By p1 { get; set; }
public By p2 { get; set; }
public string assertion { get; set; }
}
public class TheoryWrapper<T> : IXunitSerializable
{
public TheoryWrapper(string label, T #object)
{
Name = label;
Object = #object;
}
public TheoryWrapper()
{
}
public string Name { get; set; }
public T Object { get; set; }
public void Deserialize(IXunitSerializationInfo info)
{
Name = info.GetValue<string>("Label");
Object = JsonConvert.DeserializeObject<T>(info.GetValue<string>("objValue"));
}
public void Serialize(IXunitSerializationInfo info)
{
info.AddValue("Label", Name, typeof(string));
var json = JsonConvert.SerializeObject(Object);
info.AddValue("objValue", json);
}
public override string ToString()
{
return Name;
}
}
}
Working Test
public static IEnumerable<object[]> ComplexTheoryData
{
get
{
return new List<object[]>
{
new object[] {0, new TheoryWrapper<ParameterizedHook>("Pass0", new ParameterizedHook { p1 = nav_hold.pip_builder.dash_expand_pip_builder_menu, p2 = nav_hold.pip_builder.dash_project_stages, assertion = "WORK STAGE" })},
new object[] {0, new TheoryWrapper<ParameterizedHook>("Pass0", new ParameterizedHook { p1 = nav_hold.pip_builder.dash_expand_pip_builder_menu, p2 = nav_hold.pip_builder.dash_project_stages, assertion = "WORK STAGES" })},
//new object[] {0, new TheoryWrapper<ParameterizedHook>("Pass0", new ParameterizedHook { TestData = b.login })},
//new object[] {1, new TheoryWrapper<ParameterizedHook>("Pass1", new ParameterizedHook { TestData = b.password })}
};
}
}
[SkippableTheory]
[Trait("xUnit", "ForTestRunner")]
[MemberData(nameof(ComplexTheoryData))]
public void Test_Navigation(int id, TheoryWrapper<ParameterizedHook> test)
{
nav_met.NavMethodTest(test.Object.p1, test.Object.p2);
By page_title = By.Id("ctl00_lblPageTitle");
Assert.True(nav_met.VerifyText(page_title, test.Object.assertion));
}

Using NUnit testing with C# Collection Class Library project

/Using NUnit testing with C# Collection Class Library project
I am not able to figure out the TestFixture in this code
any help will be a great help
I have a below Test Class/
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ScoringExercise;
using ScoringExercise.Entities;
namespace ScoringExerciseTests
{
[TestFixture]
public class ScoringTests
{
readonly List<MultiChoiceItem> _assessmentItems;
public ScoringTests()
{
// Assessment items
_assessmentItems = new List<MultiChoiceItem>
{
new MultiChoiceItem()
{
ItemText = "Which city is the capital of Sweden?",
Options = new string[] {"Helsinki", "Stockholm", "Malmö", "Oslo"},
CorrectAnswerIndex = 1,
MarksAwardedIfCorrect = 1
},
new MultiChoiceItem()
{
ItemText = "Which of these cheeses normally has large round holes?",
Options = new string[] {"Emmental", "Feta", "Danish Blue", "Gruyere"},
CorrectAnswerIndex = 0,
MarksAwardedIfCorrect = 1
},
new MultiChoiceItem()
{
ItemText = "Which of the following is not a root vegetable?",
Options = new string[] {"Carrot", "Parsnip", "Turnip", "Shallot"},
CorrectAnswerIndex = 3,
MarksAwardedIfCorrect = 4
},
new MultiChoiceItem()
{
ItemText = "What colour is the outmost archery target ring?",
Options = new string[] {"White", "Yellow", "Red", "Black"},
CorrectAnswerIndex = 0,
MarksAwardedIfCorrect = 1
},
new MultiChoiceItem()
{
ItemText = "What is the chemical symbol for silver?",
Options = new string[] {"Au", "Sr", "Si", "Ag"},
CorrectAnswerIndex = 3,
MarksAwardedIfCorrect = 2
}
};
}
[Test]
public void AllCorrect()
{
// create test data where all items have corresponding responses
// and all responses are correct
Dictionary<int, int> responses = new Dictionary<int, int>();
int i = 0;
foreach (MultiChoiceItem item in _assessmentItems)
{
responses.Add(i, item.CorrectAnswerIndex);
i++;
}
// check that actual results are in line with expected results
AssessmentResults expected = new AssessmentResults()
{
ItemsAttempted = _assessmentItems.Count,
ItemsCorrect = _assessmentItems.Count,
TotalMarksAwarded = _assessmentItems.Sum(item => item.MarksAwardedIfCorrect)
};
AssessmentResults actual = ScoringEngine.GetResults(_assessmentItems, responses);
AssertValueEquality(expected, actual);
}
[Test]
public void AllWrong()
{
// create test data where all items have corresponding responses
// and all responses are wrong
Dictionary<int, int> responses = new Dictionary<int, int>();
int i = 0;
foreach (MultiChoiceItem item in _assessmentItems)
{
if ((item.CorrectAnswerIndex + 1) < item.Options.Length)
responses.Add(i, item.CorrectAnswerIndex + 1);
else
responses.Add(i, item.CorrectAnswerIndex - 1);
i++;
}
// check that actual results are in line with expected results
AssessmentResults expected = new AssessmentResults()
{
ItemsAttempted = responses.Count,
ItemsCorrect = 0,
TotalMarksAwarded = 0
};
AssessmentResults actual = ScoringEngine.GetResults(_assessmentItems, responses);
AssertValueEquality(expected, actual);
}
private void AssertValueEquality(AssessmentResults expected, AssessmentResults actual)
{
CollectionAssert.AreEqual(
new int[] { expected.ItemsAttempted, expected.ItemsCorrect,
expected.TotalMarksAwarded },
new int[] { actual.ItemsAttempted, actual.ItemsCorrect,
actual.TotalMarksAwarded }
);
}
}
}
/How can I implement GetResults method in my Class Library project which is as below
I am not able to figure out the TestFixture in this code
any help will be a great help/
using System.Collections.Generic;
using ScoringExercise.Entities;
using System.Linq;
using System.Collections;
namespace ScoringExercise
{
public static class ScoringEngine
{
/// <summary>
/// Calculates the results of an assessment based upon the test content and candidate
/// responses.
/// </summary>
public static AssessmentResults GetResults(List<MultiChoiceItem> multiChoiceItems,
Dictionary<int, int> responses)
{
//return null;
}
}
}
namespace ScoringExercise.Entities
{
/// <summary>
/// Represents a single multi-choice item in an assessment
/// </summary>
public class MultiChoiceItem
{
// the text associated with the item aka the question
public string ItemText { get; set; }
// the option strings from which the candidate chooses a response
public string[] Options { get; set; }
// the index of the correct answer from within the Options array
public int CorrectAnswerIndex { get; set; }
// the number of marks awarded if the correct response is chosen
public int MarksAwardedIfCorrect { get; set; }
}
}
namespace ScoringExercise.Entities
{
/// <summary>
/// Represents the results of a single assessment instance
/// </summary>
public class AssessmentResults
{
public int ItemsAttempted { get; set; }
public int ItemsCorrect { get; set; }
public int TotalMarksAwarded { get; set; }
}
}
public static AssessmentResults GetResults(List<MultiChoiceItem> multiChoiceItems, Dictionary<int, int> responses)
{
int i = 0;
int ItemsCorrect = 0;
int TotalMarksAwarded = 0;
foreach (var item in multiChoiceItems.Where(c => responses.ContainsKey(c.CorrectAnswerIndex)))
{
if (item.CorrectAnswerIndex == responses[i])
{
ItemsCorrect++;
TotalMarksAwarded += item.MarksAwardedIfCorrect;
}
i++;
}
return new AssessmentResults
{
ItemsAttempted = responses.Count,
ItemsCorrect = ItemsCorrect,
TotalMarksAwarded = TotalMarksAwarded
};
}
}

WCF Data Service return Complex Type

I created a ComplexType and am returning it in a service operation as shown here:
[WebGet]
public IQueryable<ComplexAddressType> GetCityByZip(string zip)
{
List<AddressType> normalizeAddress = NormalizeAddressProcess(new AddressType
{
ZIP = zip,
}).AddressList;
return normalizeAddress.Select(x =>new ComplexAddressType
{
ZIP = x.zip,
City = x.City,
State = x.State
}).AsQueryable();
}
When I try to invoke the service operation by calling http://localhost/MyService.svc/GetCityByZip?zip='20000', the service operation invocation works and the browser displays a list of cities.
When I try to invoke the service operation by calling http://localhost/MyService.svc/GetCityByZip?zip='20000'&$top=1, the browser displays an error page.
Could you can help me?
Assuming ComplexAddressType is actually a complex type, you cannot use the $top system query option with that service operation. If you enable verbose errors per the comment above, you are likely getting back this error:
Query options $orderby, $inlinecount, $skip and $top cannot be applied to the requested resource.
To be able to use $top with the service operation, you will need to return a collection of entity types rather than complex types.
You could also just introduce another parameter to your function call, so that you can use a URL such as the following:
http://localhost:59803/ScratchService.svc/GetProfiles?startsWith='ABC'&top=2
Sample code:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace Scratch.Web
{
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class ScratchService : DataService<ScratchContext>
{
static ScratchService()
{
Database.SetInitializer(new ScratchContextInitializer());
}
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
config.UseVerboseErrors = true;
}
[WebGet]
public IQueryable<User> GetUsers(int numUsers)
{
var users = new List<User>();
for (int i = 0; i < numUsers; i++)
{
users.Add(new User
{
Id = i,
Password = i.ToString(),
Username = i.ToString()
});
}
return users.AsQueryable();
}
[WebGet]
public IQueryable<Profile> GetProfiles(string startsWith, int top)
{
var profiles = new List<Profile>
{
new Profile{ DisplayName = "A", Preferences = "1" },
new Profile{ DisplayName = "AB", Preferences = "2" },
new Profile{ DisplayName = "ABC", Preferences = "3" },
new Profile{ DisplayName = "ABCD", Preferences = "4" },
new Profile{ DisplayName = "ABCDE", Preferences = "5" },
new Profile{ DisplayName = "ABCDEF", Preferences = "6" },
new Profile{ DisplayName = "ABCDEFG", Preferences = "7" }
};
return profiles.Where(p => p.DisplayName.StartsWith(startsWith)).Take(top).AsQueryable();
}
}
public class ScratchContextInitializer : DropCreateDatabaseAlways<ScratchContext>
{
}
public class ScratchContext : DbContext
{
public DbSet<User> Users { get; set; }
}
public class Profile
{
public string DisplayName { get; set; }
public string Preferences { get; set; }
}
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public Profile Profile { get; set; }
}
}
Last code will work when GetCityByZip method has 2 parameters. First one for zip and second one for top. In your case you have parameters inconsistency and wcf can't find method.

Serializing object graph using MongoDB Bson serializer

I've been playing a little with the MongoDB Bson serializer, using the following piece of code:
class Program
{
public class myValue
{
public int Id = 0;
public string Label = "";
}
public class myValueMap : Dictionary<string, myValue>
{
}
public class myProdData
{
public myValueMap Mapping { get; set; }
}
public class mySystemPosition
{
public string Text { get; set; }
public myProdData ProdData { get; set; }
}
static void Main(string[] args)
{
BsonClassMap.RegisterClassMap<mySystemPosition>();
BsonClassMap.RegisterClassMap<myProdData>();
BsonClassMap.RegisterClassMap<myValueMap>();
BsonClassMap.RegisterClassMap<myValue>();
var o = new mySystemPosition()
{
ProdData = new myProdData()
{
Mapping = new myValueMap()
{
{"123", new myValue() {Id = 1, Label = "Item1"}},
{"345", new myValue() {Id = 2, Label = "Item2"}},
}
}
};
var bson = o.ToBson();
var text = Encoding.ASCII.GetString(bson);
}
}
however I don't seem to be able to get the myProdData.Mapping serialized....
Do I need to configure the MongoDB Bson serializer in a special way, to make this work?
You no need to use BsonClassMap.RegisterClassMap if you no need custom serializtion(documentation).
All your classes will be desirialzied according to default rules.
Also i am changed your example a little bit to get it work(i've replaces myValueMap class with Dictionary):
public class myProdData
{
public Dictionary<string, myValue> Mapping { get; set; }
}
static void Main(string[] args)
{
var o = new mySystemPosition()
{
ProdData = new myProdData()
{
Mapping = new Dictionary<string, myValue>()
{
{"123", new myValue() {Id = 1, Label = "Item1"}},
{"345", new myValue() {Id = 2, Label = "Item2"}},
}
}
};
var json = o.ToJson();
Console.WriteLine(json);
Console.ReadKey();
}
Here is console output(just well formatted):
{
"Text":null,
"ProdData":{
"Mapping":{
"123":{
"_id":1,
"Label":"Item1"
},
"345":{
"_id":2,
"Label":"Item2"
}
}
}
}
You can test your serializtion using ToJson() extention method, in order to view that all correct and after that use ToBson() if need.
The problem is that myValueMap derives from Dictionary. That results in a class that the AutoMap method can't handle.
I recommend you just use the Dictionary directly, as Andrew did in his reply.
Ufortunately the myValueMap is an object that I can't easily change, however it turns out, that's pretty easy to create your own (de)serializer....
public class myValueMapSerializer : IBsonSerializer
{
public object Deserialize(Bson.IO.BsonReader bsonReader, System.Type nominalType, System.Type actualType, IBsonSerializationOptions options)
{
if (nominalType != typeof(myValueMap)) throw new ArgumentException("Cannot serialize anything but myValueMap");
var res = new myValueMap();
var ser = new DictionarySerializer<string, myValue>();
var dic = (Dictionary<string, myValue>)ser.Deserialize(bsonReader, typeof(Dictionary<string, myValue>), options);
foreach (var item in dic)
{
res.Add(item.Key, item.Value);
}
return res;
}
public object Deserialize(Bson.IO.BsonReader bsonReader, System.Type nominalType, IBsonSerializationOptions options)
{
throw new Exception("Not implemented");
}
public bool GetDocumentId(object document, out object id, out IIdGenerator idGenerator)
{
id = null;
idGenerator = null;
return false;
}
public void Serialize(Bson.IO.BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
if (nominalType != typeof(myValueMap)) throw new ArgumentException("Cannot serialize anything but myValueMap");
var ser = new DictionarySerializer<string, myValue>();
ser.Serialize(bsonWriter, typeof(DictionarySerializer<string, myValue>), value, options);
}
public void SetDocumentId(object document, object id)
{
return;
}
}

How do I test "Parameters Passed In Final Call" using RhinoMocks?

What's the best way in Rhino Mocks to test that a particular parameter is passed on the FINAL call to a method? Eg mockview.SetSomething(myObj) might be called any number of times by mockview.Init, but I want to test that the last time it's called as mockview.SetSomething(inParticular).
Now I know I can use GetArgumentsForCallsMadeOn with this, but my problem is that it doesn't work if I've subsequently changed the parameter holding variable. e.g
public interface IView
{
void SetSomething(ViewData data);
}
public class ViewData
{
public int Age { get; set; }
public string Name { get; set; }
public ViewData Person(int age, string name)
{
Age = age;
Name = name;
return (this);
}
}
public class WorkingPresenter
{
public void Init(IView view)
{
var data = new ViewData {Age = 1, Name = "One"};
view.SetSomething(data);
data = new ViewData {Age = 2, Name = "Two"};
view.SetSomething(data);
data = new ViewData {Age = 3, Name = "Three"};
}
}
public class NotWorkingPresenter
{
private ViewData _data;
public void Init(IView view)
{
_data = new ViewData();
view.SetSomething(_data.Person(1, "One"));
view.SetSomething(_data.Person(2, "Two"));
_data.Person(3, "Three");
}
}
then my tests are ...
[Test]
public void GetDataOfLastCall()
{
ViewData dummydata=null;
var view = MockRepository.GenerateStub<IView>();
//Approach 1 : This works
var workingPresenter = new WorkingPresenter();
workingPresenter.Init(view);
var lastCall = view.GetArgumentsForCallsMadeOn(v => v.SetSomething(dummydata)).Count - 1;
var lastParams = view.GetArgumentsForCallsMadeOn(v => v.SetSomething(dummydata))[lastCall];
var lastData = (ViewData)lastParams[0];
//Approach 2: This doesn't
var notWorkingPresenter = new NotWorkingPresenter();
notWorkingPresenter.Init(view);
lastCall = view.GetArgumentsForCallsMadeOn(v => v.SetSomething(dummydata)).Count - 1;
lastParams = view.GetArgumentsForCallsMadeOn(v => v.SetSomething(dummydata))[lastCall];
lastData = (ViewData)lastParams[0];
What I want is to verify that the last call to SetSomething was with {name="Two", age=2}. Now workingPresenter does this but wouldn't you expect notWorkingPresenter to do so too?
There must be something else going on in your code (outside of the mocking). I just threw together a few items:
public interface IView
{
void SetSomething(ViewData data);
}
public class ViewData
{
public int Age { get; set; }
public string Name { get; set; }
}
And I tested it with:
[TestMethod]
public void GetDataOfLastCall()
{
var view = MockRepository.GenerateStub<IView>();
var data = new ViewData {Age = 1, Name = "One"};
view.SetSomething(data);
data = new ViewData { Age = 2, Name = "Two" };
view.SetSomething(data);
data = new ViewData { Age = 3, Name = "Three" };
var lastCall = view.GetArgumentsForCallsMadeOn(v => v.SetSomething(data)).Count - 1;
var lastParams = view.GetArgumentsForCallsMadeOn(v => v.SetSomething(data))[lastCall];
var lastData = (ViewData) lastParams[0];
}
And I got the values of 2 and "Two" inside the ViewData. It appears Rhino.Mocks supports what you want to do. Could you create a failing test case that shows the issue identified in your original question (where you got a reference to the most recent information)?