Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Source/Mockolate/Interactions/MockInteractions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ TInteraction IMockInteractions.RegisterInteraction<TInteraction>(TInteraction in
{
_missingVerification?.Add(interaction);
_interactions.TryAdd(interaction.Index, interaction);
InteractionAdded?.Invoke(this, EventArgs.Empty);
return interaction;
}

Expand All @@ -46,6 +47,7 @@ public IReadOnlyCollection<IInteraction> GetUnverifiedInteractions()
return _missingVerification;
}

internal event EventHandler? InteractionAdded;
internal event EventHandler? OnClearing;

internal int GetNextIndex()
Expand Down
66 changes: 22 additions & 44 deletions Source/Mockolate/MockRegistration.Verify.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mockolate.Interactions;
Expand All @@ -18,23 +17,17 @@ public VerificationResult<T> Method<T>(T subject, IMethodMatch methodMatch)
=> new(
subject,
Interactions,
Interactions.Interactions
.OfType<MethodInvocation>()
.Where(methodMatch.Matches)
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is MethodInvocation method &&
methodMatch.Matches(method),
$"invoked method {methodMatch}");

/// <summary>
/// Counts the getter accesses of property <paramref name="propertyName" /> on the <paramref name="subject" />.
/// </summary>
public VerificationResult<T> Property<T>(T subject, string propertyName) => new(subject,
Interactions,
Interactions.Interactions
.OfType<PropertyGetterAccess>()
.Where(property => property.Name.Equals(propertyName))
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is PropertyGetterAccess property &&
property.Name.Equals(propertyName),
$"got property {propertyName.SubstringAfterLast('.')}");

/// <summary>
Expand All @@ -45,12 +38,9 @@ public VerificationResult<T> Property<T>(T subject, string propertyName,
IParameter value)
=> new(subject,
Interactions,
Interactions.Interactions
.OfType<PropertySetterAccess>()
.Where(property => property.Name.Equals(propertyName) &&
value.Matches(property.Value))
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is PropertySetterAccess property &&
property.Name.Equals(propertyName) &&
value.Matches(property.Value),
$"set property {propertyName.SubstringAfterLast('.')} to value {value}");

/// <summary>
Expand All @@ -61,14 +51,11 @@ public VerificationResult<T> Indexer<T>(T subject,
params NamedParameter[] parameters)
=> new(subject,
Interactions,
Interactions.Interactions
.OfType<IndexerGetterAccess>()
.Where(indexer => indexer.Parameters.Length == parameters.Length &&
!parameters
.Where((parameter, i) => !parameter.Matches(indexer.Parameters[i]))
.Any())
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is IndexerGetterAccess indexer &&
indexer.Parameters.Length == parameters.Length &&
!parameters
.Where((parameter, i) => !parameter.Matches(indexer.Parameters[i]))
.Any(),
$"got indexer [{string.Join(", ", parameters.Select(x => x.Parameter.ToString()))}]");

/// <summary>
Expand All @@ -79,39 +66,30 @@ public VerificationResult<T> Indexer<T>(T subject, IParameter? value,
params NamedParameter[] parameters)
=> new(subject,
Interactions,
Interactions.Interactions
.OfType<IndexerSetterAccess>()
.Where(indexer => indexer.Parameters.Length == parameters.Length &&
(value?.Matches(indexer.Value) ?? indexer.Value is null) &&
!parameters
.Where((parameter, i) => !parameter.Matches(indexer.Parameters[i]))
.Any())
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is IndexerSetterAccess indexer &&
indexer.Parameters.Length == parameters.Length &&
(value?.Matches(indexer.Value) ?? indexer.Value is null) &&
!parameters
.Where((parameter, i) => !parameter.Matches(indexer.Parameters[i]))
.Any(),
$"set indexer [{string.Join(", ", parameters.Select(x => x.Parameter.ToString()))}] to value {value?.ToString() ?? "null"}");

/// <summary>
/// Counts the subscriptions to the event <paramref name="eventName" /> on the <paramref name="subject" />.
/// </summary>
public VerificationResult<T> SubscribedTo<T>(T subject, string eventName)
=> new(subject, Interactions,
Interactions.Interactions
.OfType<EventSubscription>()
.Where(@event => @event.Name.Equals(eventName))
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is EventSubscription @event &&
@event.Name.Equals(eventName),
$"subscribed to event {eventName.SubstringAfterLast('.')}");

/// <summary>
/// Counts the unsubscriptions from the event <paramref name="eventName" /> on the <paramref name="subject" />.
/// </summary>
public VerificationResult<T> UnsubscribedFrom<T>(T subject, string eventName)
=> new(subject, Interactions,
Interactions.Interactions
.OfType<EventUnsubscription>()
.Where(@event => @event.Name.Equals(eventName))
.Cast<IInteraction>()
.ToArray(),
interaction => interaction is EventUnsubscription @event &&
@event.Name.Equals(eventName),
$"unsubscribed from event {eventName.SubstringAfterLast('.')}");

/// <summary>
Expand Down
16 changes: 10 additions & 6 deletions Source/Mockolate/Verify/VerificationResult.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Mockolate.Interactions;

namespace Mockolate.Verify;
Expand All @@ -10,16 +11,18 @@ public class VerificationResult<TVerify> : IVerificationResult<TVerify>, IVerifi
{
private readonly string _expectation;
private readonly MockInteractions _interactions;
private readonly IInteraction[] _matchingInteractions;
private readonly Func<IInteraction, bool> _predicate;
private readonly TVerify _verify;

/// <inheritdoc cref="VerificationResult{TMock}" />
public VerificationResult(TVerify verify, MockInteractions interactions, IInteraction[] matchingInteractions,
public VerificationResult(TVerify verify,
MockInteractions interactions,
Func<IInteraction, bool> predicate,
string expectation)
Comment thread
vbreuss marked this conversation as resolved.
{
_verify = verify;
_interactions = interactions;
_matchingInteractions = matchingInteractions;
_predicate = predicate;
_expectation = expectation;
}

Expand All @@ -32,7 +35,7 @@ TVerify IVerificationResult<TVerify>.Object
#endregion

internal VerificationResult<T> Map<T>(T mock)
=> new(mock, _interactions, _matchingInteractions, _expectation);
=> new(mock, _interactions, _predicate, _expectation);

#region IVerificationResult

Expand All @@ -47,8 +50,9 @@ MockInteractions IVerificationResult.MockInteractions
/// <inheritdoc cref="IVerificationResult.Verify(Func{IInteraction[], Boolean})" />
bool IVerificationResult.Verify(Func<IInteraction[], bool> predicate)
{
_interactions.Verified(_matchingInteractions);
return predicate(_matchingInteractions);
IInteraction[] matchingInteractions = _interactions.Interactions.Where(_predicate).ToArray();
_interactions.Verified(matchingInteractions);
return predicate(matchingInteractions);
Comment thread
vbreuss marked this conversation as resolved.
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion Tests/Mockolate.Api.Tests/Expected/Mockolate_net10.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1796,7 +1796,7 @@ namespace Mockolate.Verify
}
public class VerificationResult<TVerify> : Mockolate.Verify.IVerificationResult, Mockolate.Verify.IVerificationResult<TVerify>
{
public VerificationResult(TVerify verify, Mockolate.Interactions.MockInteractions interactions, Mockolate.Interactions.IInteraction[] matchingInteractions, string expectation) { }
public VerificationResult(TVerify verify, Mockolate.Interactions.MockInteractions interactions, System.Func<Mockolate.Interactions.IInteraction, bool> predicate, string expectation) { }
}
}
namespace Mockolate.Web
Expand Down
2 changes: 1 addition & 1 deletion Tests/Mockolate.Api.Tests/Expected/Mockolate_net8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1795,7 +1795,7 @@ namespace Mockolate.Verify
}
public class VerificationResult<TVerify> : Mockolate.Verify.IVerificationResult, Mockolate.Verify.IVerificationResult<TVerify>
{
public VerificationResult(TVerify verify, Mockolate.Interactions.MockInteractions interactions, Mockolate.Interactions.IInteraction[] matchingInteractions, string expectation) { }
public VerificationResult(TVerify verify, Mockolate.Interactions.MockInteractions interactions, System.Func<Mockolate.Interactions.IInteraction, bool> predicate, string expectation) { }
}
}
namespace Mockolate.Web
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1744,7 +1744,7 @@ namespace Mockolate.Verify
}
public class VerificationResult<TVerify> : Mockolate.Verify.IVerificationResult, Mockolate.Verify.IVerificationResult<TVerify>
{
public VerificationResult(TVerify verify, Mockolate.Interactions.MockInteractions interactions, Mockolate.Interactions.IInteraction[] matchingInteractions, string expectation) { }
public VerificationResult(TVerify verify, Mockolate.Interactions.MockInteractions interactions, System.Func<Mockolate.Interactions.IInteraction, bool> predicate, string expectation) { }
}
}
namespace Mockolate.Web
Expand Down
37 changes: 37 additions & 0 deletions Tests/Mockolate.Internal.Tests/MockInteractionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Mockolate.Interactions;

namespace Mockolate.Internal.Tests;

public class MockInteractionsTests
{
[Fact]
public async Task InteractionAdded_ShouldIncludeInteraction()
{
int interactionCount = 0;
MockInteractions sut = new();
MethodInvocation interaction = new(0, "foo", []);
sut.InteractionAdded += OnInteractionAdded;

((IMockInteractions)sut).RegisterInteraction(interaction);

sut.InteractionAdded -= OnInteractionAdded;

await That(interactionCount).IsEqualTo(1);

void OnInteractionAdded(object? sender, EventArgs e)
{
interactionCount++;
}
}

[Fact]
public async Task RegisterInteraction_ShouldRegisterInteraction()
{
MockInteractions sut = new();
MethodInvocation interaction = new(0, "foo", []);

MethodInvocation registeredInteraction = ((IMockInteractions)sut).RegisterInteraction(interaction);

await That(registeredInteraction).IsSameAs(interaction);
}
}
5 changes: 3 additions & 2 deletions Tests/Mockolate.Tests/ItTests.MatchesTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.RegularExpressions;
using Mockolate.Parameters;
using Mockolate.Verify;

namespace Mockolate.Tests;

Expand Down Expand Up @@ -58,8 +59,8 @@ public async Task AsRegex_WithTimeout_ShouldApplyTimeoutToRegex()

void Act()
{
_ = mock.VerifyMock.Invoked.DoSomethingWithString(
It.Matches("F[aeiou]+o").AsRegex(timeout: TimeSpan.FromSeconds(0)));
mock.VerifyMock.Invoked.DoSomethingWithString(
It.Matches("F[aeiou]+o").AsRegex(timeout: TimeSpan.FromSeconds(0))).AtLeastOnce();
}

await That(Act)
Expand Down
20 changes: 20 additions & 0 deletions Tests/Mockolate.Tests/Verify/MockVerifyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,24 @@ public async Task ThatAllSetupsAreUsed_WithUsedSetup_ShouldReturnTrue()

await That(sut.VerifyMock.ThatAllSetupsAreUsed()).IsTrue();
}

[Fact]
public async Task VerificationResult_ShouldUpdateWhenInteractionsChange()
{
IChocolateDispenser sut = Mock.Create<IChocolateDispenser>();

IVerificationResult result = sut.VerifyMock.Invoked.Dispense(It.Is("Dark"), It.IsAny<int>());
bool r0 = result.Verify(f => f.Length == 0);
sut.Dispense("Dark", 1);
bool r1 = result.Verify(f => f.Length == 1);
sut.Dispense("White", 2);
bool r2 = result.Verify(f => f.Length == 1);
sut.Dispense("Dark", 2);
bool r3 = result.Verify(f => f.Length == 2);

await That(r0).IsTrue().Because("No interaction was performed yet");
await That(r1).IsTrue().Because("One interaction was performed");
await That(r2).IsTrue().Because("The second interaction did not match");
await That(r3).IsTrue().Because("The third interaction did again match");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ await That(void () => mock.VerifyMock.Invoked.Dispense(It.IsAny<string>(), It.Is
public async Task Then_WhenNoMock_ShouldThrowMockException()
{
IChocolateDispenser mock = new MyChocolateDispenser();
VerificationResult<IChocolateDispenser> result = new(mock, new MockInteractions(), [], "foo");
VerificationResult<IChocolateDispenser> result = new(mock, new MockInteractions(), _ => false, "foo");

void Act()
{
Expand Down