I have a method that I´m trying to mock using NSubstitute:
Foo MyMethod(IEnumerable<string> args);
I want the method to return new Foo { ID = 1 } for a call where the args-collection has exactly one item called "Item1". However when the collection contains only "Item2" I´d like to return another instance of Foo.
So I wrote this code:
var mock = Substitute.For<MyType>();
mock.MyMethod(new[] { "Item1" }).Returns(new Foo { ID = 1 });
mock.MyMethod(new[] { "Item2" }).Returns(new Foo { ID = 2 });
In my calling code I have something like this:
var foo = myType.MyMethod(new[] { "Item1" });
However the mock isn´t executed as arrays are compared using reference-equality. So as I have two instances of string[] sharing the same values they are considered unequal and thus we don´t jump to the mocked return-statement.
So what I´d like to achieve is no matter what exact type of collection we provide to the method the mock should just distinguish on the collections items.
You can use the Arg.Is syntax to do the check yourself:
mock.MyMethod(Arg.Is<string[]>(a => a.Contains("Item1"))).Returns(new Foo { ID = 1 });
mock.MyMethod(Arg.Is<string[]>(a => a.Contains("Item2"))).Returns(new Foo { ID = 2 });
See here for more information: http://nsubstitute.github.io/help/return-for-args/
Related
I was digging into MVC 4 WebGrid's code, and i see it's used as this
grid.Column("Id", format: (item) => item.GetSelectLink(item.Id)),
I wasn't sure what the "item" parameter is, so I looked into the source code, and it seems like it's a "WebGridRow" class. The issue for me is, above code is looking for an ".Id" property, but it doesn't exist in the class. The only property that is anywhere close to it looks like the follwing
public object this[string name]
{
get
{
if (String.IsNullOrEmpty(name))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "name");
}
object value = null;
if (!TryGetMember(name, out value))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
HelpersResources.WebGrid_ColumnNotFound, name));
}
return value;
}
}
I have never seen a property defined like "this[string name]", what does it mean? dynamic property?
I tried to search on the web, but not sure what to search for, I couldn't come up with any results / explanation for it.
Please help. Thanks
I think there's two consents here you don't understand (or I simply don't understand your question).
this[..] properties are index-properties. They are used like array-expressions. For instance, you could imagine creating your own "array" like this:
public class MyArray {
string[] _storrage = new string[100];
public string this[int index] {
get { return _storrage[index]; }
set { _storrage[index] = value; }
}
}
You can create index-properties with multiple arguments as well, and they can be overloaded. For instance, some lists allows you to access items either by name (this[string name]) and index (this[int index]). In all actuality it's just syntactic sugar so you don't have to write methods like getItem(int index) as you do in java.
The other consept that it seems you're not understanding (though not apparent from your question) is lambda-methods. In your code:
(item) => item.GetSelectLink(item.Id)
is a lambda-method. For instance if the method Colum on your grid-object has the following signature:
public void Column<T>(string name, Func<T, string>)
the expression (item) => item.GetSelectLink(item.Id) would evaluate to a method that takes a T and returns a string. An alternative way to create the same functionality is to do this:
// in class
public string GetIdField(YourClassType item) { return item.GetSelectLink(item.Id); }
// in Column-call
grid.Column("Id", format: GetIdField);
You can read more about lambdas here: http://msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx
[Edit]
To show a quick example of a lambda that might shred some light on this:
var list = new List<string>() { "a", "b", "c" };
list.ForEach((item) => Console.WriteLine(item));
this will output "a", "b" and "c" (see it run at http://ideone.com/MGZxfr).
The equivalent (without using a lambda) would be something like this:
void Main() {
var list = new List<string>() { "a", "b", "c" };
foreach(var item in list) Print(item);
}
void Print(string item) { Console.WriteLine(item); }
It's not exactly a property, but a [] operator.
the get method will be called when you will do something like this:
var a = Ob["hello"]
and the set:
ob["hello"] = 5
It is an indexer, MSDN has you covered
This is called an indexer
You can create your own indexer property as well.
It is commonly used in collections such as Array, List or Dictionary.
http://msdn.microsoft.com/en-us/library/vstudio/6x16t2tx.aspx
I've got a method which takes a IList<Person> and returns an IEnumberable as so:
internal static IEnumerable<Dictionary<string, string>> GetPersonsPerSite(IList<Person> Data)
{
//Implementation ...
}
and I'm trying to create a mock object of IList<Person> so I can test this method.
Using Moq I have written the following:
var mockObjects = new Mock<IList<Person>>();
mockObjects.Setup(x => x[0]).Returns(new Person()
{
SITE_ID = "test",
MPAN = "test",
ADDLINE1 = "test",
ADDLINE2 = "test",
ADDRESS_LINE_1 = "test",
ADDRESS_LINE_2 = "test"
});
However when I come to use the object the IEnumerable returned is aways throwing exception Object reference not set to an instance of an object.
I'm brand new to Moq, and I'm pretty sure I'm missing a fundamental concept here, however I've successfully being able to throw exceptions and modifiy outputs with other mock objects.
I'd appreciate if someone could point me in the right direction.
Don't mock the IList. You don't need to, unless there's something specific your looking to check.
Instead just keep your test simple and do something like this:
var testData = new List<Person>(){new Person()
{
SITE_ID = "test",
MPAN = "test",
ADDLINE1 = "test",
ADDLINE2 = "test",
ADDRESS_LINE_1 = "test",
ADDRESS_LINE_2 = "test"
}};
var result = GetPersonsePerSite(testData);
The code you have got there looks fine and does work for me. Can you expand with an example of where you actually consume the mockObjects.Object and find it null?
Also, do you really need to mock your IList<Person>?
If you are just using it to supply test data to the method under test, just use a concrete list - there is nothing gained by using a mock for this.
Of course, you may be mocking it so you can verify certain actions are taken on it (methods called, properties accessed, etc) - in which case that is different.
Hi I have a Method like this:
public T LoadR<T, K>()
where T : ObservableCollection<K>, new()
where K : IStoreElement, new() {
T onC = new T();
//....
return (onC);
}
Further I have a class XObservableCollection which derivies from ObservableCollection.
It works as it is when I call:
Categories = LoadR<ObservableCollection<Category>,Category>();
Products = LoadR<XObservableCollection<Product>,Product>();
What I want to do is to make a call like this (avoid passing the K as extra parameter):
Categories = LoadR<ObservableCollection<Category>>();
Products = LoadR<XObservableCollection<Product>>();
I know that I could write an extension for it.
But I curious if there is a way to achive this without it.
Manfred
I don't think you can.
C# has a mechanism to understand generic agruments from method paramaters when used in it, but not from other generic arguments of the same method. It doesn't work.
Maybe you can change your signature to:
private static ObservableCollection<K> LoadR<K>(.ObservableCollection<K> onC)
where K : IStoreElement, new()
{
//....
return onC;
}
Usage would be:
static void TestLoad()
{
var result1 = LoadR(new ObservableCollection<Something>());
var result2 = LoadR(new DerivedClassFromObservableCollection<Something>());
}
Which I agree is not that good, and I can se it's not what you are looking for.
But just because C# wouldn't let you try to infer the types from the generic arguments.
.....
The other way aroudn is to make it use a specific collection. I can see you don't want this even more.
So, one thing you can do is make it return IEnumerable instead, then you usage will be something like:
static void TestLoad()
{
var result1 = new ObservableCollection( LoadR<Something>() );
var result1 = new DerivedClassFromObservableCollection( LoadR<Something>() );
}
Which may not be good also if you want to do fancy things with the collection itself, because you no-longer own it.
....
I would go for the very first option myself.
I'm using NUnit 2.5.7. I want to test whether a collection of custom objects of a particular class contains certain objects, based on one of the class's properties.
e.g. a contrived example...
public class Person
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
}
// ...
public List<Person> GetFavouritePeople()
{
List<Person> favouritePeople = new List<Person>();
favouritePeople.Add(new Person("joe"));
favouritePeople.Add(new Person("fred"));
favouritePeople.Add(new Person("jenny"));
return favouritePeople;
}
// ...
[Test]
public GetFavouritePeople()
{
List<Person> people = GetFavouritePeople();
// What I'd like to test, but not sure how to do it...
Assert.Contains(Name="joe", people);
Assert.Contains(Name="fred", people);
Assert.Contains(Name="jenny", people);
}
Although it would be simple enough in this example, I don't want to create mock objects for each Person and use those in the assertion... I just want to check based on a particular property (Name in this example.)
You could use LINQ:
Assert.That(people.Any(p => p.Name == "joe"));
or, if you want to be explicit about there being exactly one person with each name:
Assert.That(people.Count(p => p.Name == "joe"), Is.EqualTo(1));
If you want a better error message than "Assertion failed, expected true, was false", you could create your own assert method.
For several collection-related asserts, CollectionAssert is very useful - for instance, it allows you to check if two collections contain the same elements, irrespective of their order. So yet another possibility is:
CollectionAssert.AreEquivalent(new[] {"joe", "fred", "jenny"}, people.Select(p => p.Name).ToList());
Note that CollectionAssert.AreEquivalent() is a little picky with regard to the types it accepts (even though the signature takes IEnumerable). I usually wrap it in another method that calls ToList() on both parameters before invoking CollectionAssert.AreEquivalent().
You can use Assert.That in conjunction with Has.Exactly(1).Matches:
List<Person> people = GetFavouritePeople()
Assert.That(people, Has.Exactly(1).Matches<Person>(p => p.Name == "NUnit is amazing")));
Failure message will be along lines of:
Expected: exactly one item value matching lambda expression
But was: 0 items < [result of people.ToString()] >
You can use Linq's Intersect() to determine whether all the expected items are within the list your testing against even if the list contains other items that you are not testing for:
[Test]
public void TestFavouritePeople()
{
var people = GetFavouritePeople();
var names = people.Select(p => p.Name);
var expectedNames = new[] {"joe", "fred", "jenny"};
var actualNames = names.Intersect(expectedNames);
CollectionAssert.AreEquivalent(expectedNames, actualNames);
}
For NUnit 3.0 and greater, you can use Is.SupersetOf():
[Test]
public void TestFavouritePeople()
{
var people = GetFavouritePeople();
var names = people.Select(p => p.Name);
var expectedNames = new[] {"joe", "fred", "jienny"};
var actualNames = names;
Assert.That(actualNames, Is.SupersetOf(expectedNames));
}
I've been looking at the Moq documentation and the comments are too short for me to understand each of things it can do.
The first thing I don't get is It.IsAny<string>(). //example using string
Is there an advantage of using this over just putting some value in? I know people say to use this if you don't care about the value, but if you don't care about the value can't you just do "a" or something? This just seems like more typing.
Secondly, when would be an example be of when you would not care about the value? I thought Moq needs the value to match up stuff.
I don't get what It.Is<> is for at all or how to use it. I don't understand the example and what it is trying to show.
Next, I don't get when to use Times (and its AtMost methods and similar). Why would you limit the number of times something is set up? I have some AppConfig value that I need to use twice. Why would I want to limit it to, say, once? This would just make the test fail. Is this to stop other people from adding another one to your code or something?
I don't get how to use mock.SetupAllProperties();
What does it set up the properties with?
I don't also get why there are so many different ways to set up a property and what their differences are. The documentation has:
SetupGet(of property)
SetupGet<TProperty>
I noticed that a lot of the stuff in Moq shows () and <> - what's the difference between them and what would they look like in use?
I also don't get why they have SetupGet. Would you not use SetupSet to set a property?
SetupSet has five different ways to use it in the documentation. Plus another one called SetupProperty. So I don't understand why there are so many.
On a side note, I am wondering if variables used in lambdas are independent of other lambdas. E.g.:
mock.setup(m => m.Test);
stop.setup(m => m.Test);
Would this be ok or would there be some conflict between the variable m?
Finally, I was watching this video and I am wondering if it shows Visual Studio. His Intellisense looks different. A lightbulb pops up for him (I am happy mine does not, as it brings back painful memories of netbeans), and there are lines going from one opening brace to the closing brace and etc.
It.IsAny / It.Is
These can be useful when you're passing a new reference type within the code under test. For instance, if you had a method along the lines of:
public void CreatePerson(string name, int age) {
Person person = new Person(name, age);
_personRepository.Add(person);
}
You might want to check the add method has been called on the repository,
[Test]
public void Create_Person_Calls_Add_On_Repository () {
Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
PersonManager manager = new PersonManager(mockRepository.Object);
manager.CreatePerson("Bob", 12);
mockRepository.Verify(p => p.Add(It.IsAny<Person>()));
}
If you wanted to make this test more explicit you can use It.Is by supplying a predicate the person object must match,
[Test]
public void Create_Person_Calls_Add_On_Repository () {
Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
PersonManager manager = new PersonManager(mockRepository.Object);
manager.CreatePerson("Bob", 12);
mockRepository.Verify(pr => pr.Add(It.Is<Person>(p => p.Age == 12)));
}
This way the test will through an exception if the person object that was used to call the add method didn't have the age property set to 12.
Times
If you had a method along the lines of:-
public void PayPensionContribution(Person person) {
if (person.Age > 65 || person.Age < 18) return;
//Do some complex logic
_pensionService.Pay(500M);
}
One of the things that you might want to test is that the pay method does not get called when a person aged over 65 is passed into the method
[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
Mock<IPensionService> mockPensionService = new Mock<IPensionService>();
Person p = new Person("test", 66);
PensionCalculator calc = new PensionCalculator(mockPensionService.Object);
calc.PayPensionContribution(p);
mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}
Similarly, it's possible to imagine situations where you're iterating over a collection and calling a method for each item in the collection and you'd like to make sure that it's been called a certain amount of times, other times you simply don't care.
SetupGet / SetupSet
What you need to be aware of with these guys is that they reflect how your code is interacting with the mock rather than how you're setting up the mock
public static void SetAuditProperties(IAuditable auditable) {
auditable.ModifiedBy = Thread.CurrentPrincipal.Identity.Name;
}
In this case, the code is setting the ModifiedBy property of the IAuditable instance while it's getting the Name property of the current instance of IPrincipal,
[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");
Thread.CurrentPrincipal = mockPrincipal.Object;
AuditManager.SetAuditProperties(mockAuditable.Object);
mockPrincipal.VerifyGet(p => p.Identity.Name);
mockAuditable.VerifySet(a => a.ModifiedBy = "test");
}
In this case, we're setting up the name property on the mock of IPrincipal so it returns "test" when the getter is called on the Name property of Identity we're not setting the property itself.
SetupProperty / SetupAllProperties
Looking at the test above if it was changed to read
[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");
var auditable = mockAuditable.Object;
Thread.CurrentPrincipal = mockPrincipal.Object;
AuditManager.SetAuditProperties(auditable);
Assert.AreEqual("test", auditable.ModifiedBy);
}
The test would fail. This is because the proxy created by Moq doesn't actually do anything in the set method of a property unless you tell it to. In effect, the mock object looks a bit like this
public class AuditableMock : IAuditable {
public string ModifiedBy { get { return null; } set { } }
}
To get the test to pass you have to tell Moq to set up the property to have the standard property behavior. You can do this by calling SetupProperty and the mock will look more like
public class AuditableMock : IAuditable {
public string ModifiedBy { get; set; }
}
and the test above would pass as the value "test" would now get stored against the mock. When mocking complex objects you might want to do this for all properties, hence the SetupAllProperties shortcut
Finally, the lightbulb in the IDE is the ReSharper plugin.
If you don't care about the exact value of a property, it's far better to use .IsAny because you are being explicit about the fact that the exact value is not important. If you hardcode it as "abc", then it is not clear if your code you are testing depends on starting with "a" or ending with "c" or being 3 chars long, etc. etc.