public void Add(Item item) { // set item created time // set item updated time repository.Add(item); }
Moq provides some argument checking methods that we can use; there are:
- It.Is<Type>(...) ,
- It.IsInRange<Type>(...) and
- It.IsRegex(...)
Below is a unit test using one of the methods; It.Is<Type>(o => checking_condition)
[Fact] public void Created_time_should_be_set_as_current_time() { // Arrange var item = new Item(); var timeToCompare = DateTime.Now.AddHours(-1); // Act itemDS.Add(item); // Assert repository.Verify(c => c.Add(It.Is<Item>(i => i.CreatedAt.CompareTo(timeToCompare) > 0))); }or we can write like this:
[Fact] public void Created_time_should_be_set_as_current_time() { // Arrange var item = new Item(); var timeToCompare = DateTime.Now.AddHours(-1); repository.Setup(c => c.Add(It.Is<Item>(i => i.CreatedAt.CompareTo(timeToCompare) > 0))); // Act itemDS.Add(item); // Assert repository.VerifyAll(); }Run the test. It will fail. Then we can put the code item.CreatedAt = DateTime.Now; on the method. Run the test again. It should pass now.
Now we want to create a test to make sure updated time is set. We will use another way to check the parameter passed to a method. We will use Callback feature to retrieve the parameter. We cannot put a checking conditional logic in Callback argument. However we can assign the passed parameter to an existing object or add it to an existing collection then later we can inspect it.
[Fact] public void Updated_time_should_be_set_as_current_time() { // Arrange var item = new Item(); var timeToCompare = DateTime.Now.AddHours(-1); // repository.Setup(c => c.Add(It.Is<Item>(i => i.UpdatedAt.CompareTo(timeToCompare) > 0))); // alternate way by using Callback repository.Setup(c => c.Add(It.IsAny<Item>())).Callback<Item>(i => item = i); // Act itemDS.Add(item); // Assert // repository.VerifyAll(); // now we are using Callback Assert.True(item.UpdatedAt.CompareTo(timeToCompare) > 0); }
Just for a note, if required, Callback can be combined with Returns function as well. For example:
mock.Setup(. . .) .Returns(. . .) .Callback(. . .) mock.Setup(. . .) .Callback(. . .) .Returns(. . .) .Callback(. . .)
Run the test. It will fail. Put the code item.UpdatedAt = DateTime.Now; Now the test will pass.
Our updated method now is
public void Add(Item item) { // set item created time item.CreatedAt = DateTime.Now; // set item updated time item.UpdatedAt = DateTime.Now; repository.Add(item); }
References:
http://code.google.com/p/moq/wiki/QuickStart
http://stackoverflow.com/questions/3269717/moq-how-to-get-to-a-parameter-passed-to-a-method-of-a-mocked-service