I am trying to test a C# method that uses a dynamic property from a C++/CLI wrapper.
The interface I am trying to mock is
property Object^ DynamicValueItem
{
[returnvalue: System::Runtime::CompilerServices::DynamicAttribute]
Object^ get () ;
}
The method I am trying to test is
public void GetBillInfo (IConfigurationItem item)
{
dynamic ValueItem = item.DynamicValueItem;
string Curr = ValueItem.Currency;
string Ser = ValueItem.BillSeries;
}
My test method is
[TestMethod()]
public void GetBillInfoTest()
{
BnrHelperMethods target = new BnrHelperMethods();
var ValueItem = new
{
Currency = "USD",
BillValue = 100,
};
var mockItem = new Mock<IConfigurationItem>();
mockItem.Setup(i => i.DynamicValueItem).Returns(ValueItem);
target.GetBillInfo(mockItem.Object);
}
I got the method for mocking the dynamic property from http://blogs.clariusconsulting.net/kzu/how-to-mock-a-dynamic-object/
The example was for a standard C# dynamic property so I have had to adapt my C++/CLI property to try and get the same effect.
My problem is that when I perform the test I get a RuntimeBinderException stating that the object does not contain the definition of for Currency. If I look at the Locals window it shows both Currency and BillValue
-ValueItem { Currency = USD, BillValue = 100 }
dynamic{<>f__AnonymousType1}
-BillValue 0x00000064 int
-Currency "USD" string
When using the method normally it works. The only difference I see is that Currency and BillValue are under a Dynamic View item in the Local window
-ValueItem {} dynamic {MEIConfiguration.ConfigurationValueItem}
-Dynamic View Expanding the Dynamic View will get the dynamic members for the object
-BillValue 0x000003e8 System.Int32
-Currency "GBP" System.String
Have I defined the C++/CLI property correctly?
Am I creating the mock correctly?
Can anyone tell me what I am doing wrong?
For anyone who is interested here is the solution provided by a colleague.
[TestMethod()]
public void GetBillInfoTest()
{
BnrHelperMethods target = new BnrHelperMethods();
dynamic valueItem = new ExpandoObject();
valueItem.Currency = "USD" ;
valueItem.BillValue = 100;
var mockItem = new Mock<IConfigurationItem>();
mockItem.Setup(i => i.DynamicValueItem).Returns ((object)valueItem);
target.GetBillInfo(mockItem.Object);
}
Related
I have a problem; I have various (too many) classes, that are linked as Parent/Child
I populate initially my top class while instantiate the others, as follows (works):
TopClass MyClass = new TopClass()
{
Headers = new someHeaders()
{
CorrID = "1234567890",
RequestID = "1234567890",
L_Token = "abcdefghijklmnopqrstuvwxyz"
},
Body = new someBody()
{
access = new AccessHeaders()
{
allPs = "allAcc",
availableAcc = "all"
},
CombinedServiceIndicator = false,
FrequencyPerDay = 10,
ValidUntil = "2020-12-31"
},
ResponseAttributes = new ConsentResponse()
{
myId = String.Empty,
myStatus = String.Empty,
myName = String.Empty,
_links_self_href = String.Empty,
status_href = String.Empty
}
};
The initials values that I populate above rarely change, but the Classes' properties change as the project goes on, and each class ends up having many properties.
I need to parse the properties and set values to any properties that match their name, but I can't seem to figure out why despite following official examples.
(I read the input data from a JSON string I use Newtonsoft - have tried everything out there)
I can't find a way to deserialize the JSON and assign any values to my properties without using the name of the property, i.e. without saying
MyClass.Body.access.allPs = "Hello"
but something like
var json = response.Content.ReadAsStringAsync().Result.ToString();
var a = new { serverTime = "", data = new object[] { } };
var c = new JsonSerializer();
or
if (myresponse.Attributes.GetType().GetTypeInfo().GetDeclaredProperty(key) != null)
myresponse.GetType().GetTypeInfo().GetDeclaredProperty(key).SetValue(myresponse, entry.Value);
//and how do I read the value, parse my TopClass and assign the value to correct property?
Could someone help me?
Values for the properties will get automatically assigned if the JSON is having the correct structure as per the class mentioned above.
Something like:
{
"Body":
"access:
{
"allPs" = "required value"
}
}
Then you can use:
var result = JsonConvert.DeserializeObject < TopClass > (json );
This may not be something that's even possible but I thought I'd ask anyway. Is there anyway for me to stub out this method so that the second call is also stubbed out using the parameter provided in the method I'm testing?
The method to stub:
public SupportDetails GetSupportDetails(string languageKey)
{
var result = FindSupportDetails(languageKey);
return result ?? FindSupportDetails("en-us");
}
My Current test:
public void GetsUSDetails_IfLangKeyDoesNotExist()
{
var langKey = "it-it";
_repo.Stub(s => s.FindSupportDetails(langKey))
.Return(supportDetails.Where(sd => sd.LanguageKey == langKey)
.SingleOrDefault());
ISupportRepository repo = _repo;
var actual = repo.GetSupportDetails(langKey);
Assert.AreEqual("en-us", actual.LanguageKey);
}
and the supportDetails object used in the test:
supportDetails = new SupportDetails[]
{
new SupportDetails()
{
ContactSupportDetailsID = 1,
LanguageKey = "en-us"
},
new SupportDetails()
{
ContactSupportDetailsID = 2,
LanguageKey = "en-gb"
},
new SupportDetails()
{
ContactSupportDetailsID = 3,
LanguageKey = "es-es"
}
};
The correct and the most elegant solution to your problem is to use Do method:
_repo.Stub(s => s.FindSupportDetails(null))
.IgnoreArguments()
.Do((Func<string, SupportDetails>)
(langKey => supportDetails.SingleOrDefault(sd => sd.LanguageKey == langKey)));
The Func will raise no matter what argument was passed to FindSupportDetails, then the correct SupportDetails will select.
i am trying to deserialize a JSON-Object which looks quite similiar to an Array.
Here's the JSON-String:
...,"Test":[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]],...
I do not want to deserialize it as 2D Array, because each of these values have an explicit meaning to me. I would like to access it like this:
Test[0].Example (0)
Test[0].Êxample2 (1)
Test[0].Example3 (2)
...
Test[2].Example (10)
I hope you got the idea and have a solution to my Problem.
I am using the Newtonsoft JSON Library together with C#.
EDIT1:
Maybe i should be more specific of how deserilisation is done until now:
JSON:"Object":{"A":0,"Test":[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]],"B":1,...}
C#:
m_Object = JsonConvert.DeserializeObject<Object>(jsonString);
The Class Object is defined in C# containing all the fields of the JSON-String.
Object-Class:
class Object
{
public Int32 A {get;set;}
public Object Test {get;set;}
public Int32 B {get;set;}
}
You can use LINQ to JSON:
string json = "[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]";
var tests = JsonConvert.DeserializeObject<JArray>(json)
.Cast<JArray>()
.Select(a => new Test {
Example = (int)a[0],
Example2 = (int)a[1]
// etc
});
Result:
UPDATE: For your updated question - you can deserialize json object, and then access its properties by their keys
string json = #"{'A':0,'Test':[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]],'B':1}";
var obj = JsonConvert.DeserializeObject<JObject>(json);
var test = (JArray)obj["Test"];
var result = new {
A = (int)obj["A"],
B = (int)obj["B"],
Test = test.Cast<JArray>().Select(a => new Test {
Example = (int)a[0],
Example2 = (int)a[1],
Example3 = (int)a[2],
Example4 = (int)a[3],
Example5 = (int)a[4]
})
};
I have a problem with RazorEngine 3.4 caching. I have a few email templates with the same #Layout but different Models for each template. It works fine until I try to use the Cache I read that not use cache: "will result in both dreadful performances and memory leaks" from here.
So I turned it on. It was simple but lead to a problem: the _Layout.cshtml is also cached with the first model type, when I try to parse an another template with a different Model it will throw an exception: "System.ArgumentException: Object of type '....model1...' cannot be converted to type '...model2...'."
I wrote 2 unit tests into "IsolatedTemplateServiceTestFixture.cs" to show the problem. The first one passes, but the second one fails because the TemplateService.SetModelExplicit() function wants to set the template.Model property with a different Model type for the Layout.
private Mock<ITemplateResolver> _templateResolver;
[Test]
public void IsolatedTemplateService_CanParseTemplateWithLayout_WithOneSerializableModels_UseCache()
{
_templateResolver = new Mock<ITemplateResolver>();
var config = new TemplateServiceConfiguration()
{
Resolver = _templateResolver.Object
};
using (var service = new TemplateService(config))
{
_templateResolver.Setup(i => i.Resolve("test")).Returns("<html>#RenderBody()</html>");
const string template = #"#{Layout=""test"";}<h1>Hello #Model.Item1</h1>";
const string expected = "<html><h1>Hello World</h1></html>";
var model = new Tuple<string>("World");
string result = service.Parse(template, model, null, "C1");
string result2 = service.Parse(template, model, null, "C1");
Assert.That(result == expected, "Result does not match expected: " + result);
Assert.That(result2 == expected, "Result does not match expected: " + result2);
}
}
[Test]
public void IsolatedTemplateService_CanParseTemplateWithLayout_WithDifferentSerializableModels_UseCache()
{
_templateResolver = new Mock<ITemplateResolver>();
var config = new TemplateServiceConfiguration()
{
Resolver = _templateResolver.Object
};
using (var service = new TemplateService(config))
{
_templateResolver.Setup(i => i.Resolve("test")).Returns("<html>#RenderBody()</html>");
const string template = #"#{Layout=""test"";}<h1>Hello #Model.Item1</h1>";
const string expected = "<html><h1>Hello World</h1></html>";
var model = new Tuple<string>("World");
string result = service.Parse(template, model, null, "C1");
string result2 = service.Parse(template, model, null, "C1");
const string template2 = #"#{Layout=""test"";}<h1>Hello2 #Model.Item1</h1>";
const string expected2 = "<html><h1>Hello2 123</h1></html>";
var model2 = new Tuple<int>(123);
string result3 = service.Parse(template2, model2, null, "C2");
Assert.That(result == expected, "Result does not match expected: " + result);
Assert.That(result2 == expected, "Result does not match expected: " + result2);
Assert.That(result3 == expected2, "Result does not match expected: " + result3);
}
}
My question is: anybody has the same problem? What would a "nice" way to workaround it until it will be fixed (if at all it happens)?
Update:
With the latest version (currently is v.3.10) both tests passed. So the problem was fixed.
As it is in RazorEngine, the layout has a fixed type, even if you don't declare a model in it. The first time the layout gets compiled by compiling a template, the template's model type becomes the layout's type as well. As you noticed, that will clash when you try to compile another template with a different type.
You can work around that by declaring the model type of the layout dynamic, i.e. #model dynamic
That should do the trick. The actual templates don't need to be altered.
I have an IRecord which contains an ICollection of Samples. The ICollection looks like this:
Sample sample1 = scope.DbContext.Samples.AddNew(new Sample
{
Name = GenerateName("Sample one"),
Tests = tests
});
Sample sample2 = scope.DbContext.Samples.AddNew(new Sample
{
Name = GenerateName("Sample two"),
Tests = tests
});
ICollection<Sample> samples = new Collection<Sample>();
samples.Add(sample1);
samples.Add(sample2);
Then I add the samples to the record:
Order record = scope.DbContext.Orders.AddNew(new Order
{
Name = GenerateName("Order"),
Samples = samples
});
Now I want to get the Samples out of the record. I know that when I do
object name = record["Name"];
I get the correctly generated name. However, when I do
object propertyValue = record["Samples"];
it has no items in it. I want to do the following:
object propertyValue = record["Samples"];
if (typeof(IEnumerable<IRecord>).IsAssignableFrom(propertyValue.GetType()))
{
foreach (var property in (IEnumerable<IRecord>)propertyValue)
{
var test = property;
}
}
So why does record["Samples"] not get the ICollection?
It looks to me, that what you really want to use is the as keyword.
var samples = record["Samples"] as ICollection<Sample>;
However, why aren't you just using the CLR static type?
var samples = record.Samples;
Maybe I am just not understanding what you are trying to do here, but it seems like it can be boiled pretty simply to the above.