Going to try working with expressions for more complex matchers to
ease burden on devs trying to use the feature.
This commit is contained in:
David Tchepak 2012-05-04 21:42:18 +10:00
Родитель 4fa50ae021
Коммит 25b699dac4
4 изменённых файлов: 0 добавлений и 116 удалений

Просмотреть файл

@ -1,8 +1,6 @@
unreleased changes
* [NEW] [BREAKING] Auto-substitute for types returned from substitutes of delegates/Funcs (follows same auto-substitute rules as for methods and properties). Thanks to Sauli Tähkäpää for implementing this feature. (#52)
* [NEW] Show details of params arguments when displaying received calls. Thanks to Sauli Tähkäpää for implementing this feature. (#65)
* [NEW] Detailed descriptions for custom argument matchers using IDescribeNonMatches interface.
* [NEW] Custom argument matchers (Arg.Matches syntax).
* [FIX] Race condition between checking received calls and building the exception could cause nonsensical exception messages like "Expected 5, actually received 5" when called concurrently. (#64)
1.3.0 (Nov 2011)

Просмотреть файл

@ -175,23 +175,6 @@ namespace NSubstitute.Acceptance.Specs
Assert.That(_something.Anything(new object()), Is.EqualTo(123));
}
[Test]
public void With_custom_matcher()
{
_something.Add(1, 10);
_something.Received().Add(1, Arg.Matches(new LessThanMatcher(20)));
_something.DidNotReceive().Add(1, Arg.Matches(new LessThanMatcher(3)));
}
private class LessThanMatcher : IArgumentMatcher<int>, IDescribeNonMatches
{
private readonly int _lessThan;
public LessThanMatcher(int lessThan) { _lessThan = lessThan; }
public bool IsSatisfiedBy(int argument) { return argument < _lessThan; }
public string DescribeFor(object argument) { return string.Format("Expected less than {0}\nActually got {1}", _lessThan, argument); }
}
[SetUp]
public void SetUp()
{

Просмотреть файл

@ -316,79 +316,6 @@ namespace NSubstitute.Acceptance.Specs
}
}
public class When_using_custom_describable_matcher : Context
{
private Car _expectedCar;
private IGarage _sub;
private Car _delorean;
private Car _prius2010;
public class Car
{
public Car(string make, string model, int year) { Make = make; Model = model; Year = year; }
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
}
public interface IGarage { void Add(Car c, int quantity); }
private class CarMatcher : IArgumentMatcher<Car>, IDescribeNonMatches
{
private readonly Car _expectedCar;
public CarMatcher(Car expectedCar) { _expectedCar = expectedCar; }
public bool IsSatisfiedBy(Car argument)
{
return _expectedCar.Make == argument.Make && _expectedCar.Model == argument.Model && _expectedCar.Year == argument.Year;
}
public string DescribeFor(object argument)
{
return "Expected: " + FormatCar(_expectedCar) + "\nActual: " + FormatCar((Car)argument);
}
public string FormatCar(Car c) { return string.Format("{0} {1} ({2})", c.Make, c.Model, c.Year); }
public override string ToString() { return "specific Car"; }
}
protected override void ConfigureContext()
{
_expectedCar = new Car("Toyota", "Prius", 2012);
_delorean = new Car("DeLorean", "DMC-12", 1981);
_prius2010 = new Car("Toyota", "Prius", 2010);
_sub = Substitute.For<IGarage>();
_sub.Add(_delorean, 1);
_sub.Add(_prius2010, 10);
}
protected override void ExpectedCall()
{
_sub.Received().Add(Arg.Matches(new CarMatcher(_expectedCar)), 10);
}
[Test]
public void Should_show_matcher_string_in_expected_call()
{
ExceptionMessageContains(ExpectedCallMessagePrefix + "Add(specific Car, 10)");
}
[Test]
public void Should_show_matcher_description_for_non_matching_Prius()
{
ExceptionMessageContains("arg[0]: Expected: Toyota Prius (2012)");
ExceptionMessageContains("Actual: Toyota Prius (2010)");
}
[Test]
public void Should_show_matcher_description_for_non_matching_DeLorean()
{
ExceptionMessageContains("arg[0]: Expected: Toyota Prius (2012)");
ExceptionMessageContains("Actual: DeLorean DMC-12 (1981)");
}
}
public abstract class Context
{
protected const string ExpectedCallMessagePrefix = "Expected to receive a call matching:\n\t";

Просмотреть файл

@ -45,30 +45,6 @@ namespace NSubstitute
return ArgSpecQueue.EnqueueSpecFor<T>(new ExpressionArgumentMatcher<T>(predicate));
}
/// <summary>
/// Match an argument compatible with type <typeparamref name="T"/> that satisfies the given <paramref name="matcher" />.
/// If the <paramref name="matcher"/> throws an exception for an argument it will be treated as non-matching.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="matcher"></param>
/// <returns></returns>
public static T Matches<T>(IArgumentMatcher<T> matcher)
{
return ArgSpecQueue.EnqueueSpecFor(matcher);
}
/// <summary>
/// Match an argument compatible with type <typeparamref name="T"/> that satisfies the given <paramref name="matcher" />.
/// If the <paramref name="matcher"/> throws an exception for an argument it will be treated as non-matching.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="matcher"></param>
/// <returns></returns>
public static T Matches<T>(IArgumentMatcher matcher)
{
return ArgSpecQueue.EnqueueSpecFor<T>(matcher);
}
/// <summary>
/// Invoke any <see cref="Action"/> argument as soon as a matching call is made to the substitute.
/// </summary>