Browse Source

Migration to fake it easy completed.

pull/95/head
Sebastian Stehle 9 years ago
parent
commit
92a380d925
  1. 2
      tests/Squidex.Domain.Apps.Write.Tests/TestHelpers/HandlerTestBase.cs
  2. 6
      tests/Squidex.Infrastructure.Tests/Assets/FolderAssetStoreTests.cs
  3. 64
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/AggregateHandlerTests.cs
  4. 4
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/CommandContextTests.cs
  5. 16
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/DefaultDomainObjectFactoryTests.cs
  6. 63
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/DefaultDomainObjectRepositoryTests.cs
  7. 15
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs
  8. 4
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs
  9. 4
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/LogExceptionHandlerTests.cs
  10. 4
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/LogExecutingHandlerTests.cs
  11. 56
      tests/Squidex.Infrastructure.Tests/CQRS/Events/CompoundEventConsumerTests.cs
  12. 74
      tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs
  13. 28
      tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs
  14. 12
      tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs
  15. 12
      tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs
  16. 2
      tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
  17. 35
      tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs

2
tests/Squidex.Domain.Apps.Write.Tests/TestHelpers/HandlerTestBase.cs

@ -57,7 +57,7 @@ namespace Squidex.Domain.Apps.Write.TestHelpers
}
}
private readonly MockupHandler handler = A.DummyupHandler();
private readonly MockupHandler handler = new MockupHandler();
protected RefToken User { get; } = new RefToken("subject", Guid.NewGuid().ToString());

6
tests/Squidex.Infrastructure.Tests/Assets/FolderAssetStoreTests.cs

@ -8,7 +8,7 @@
using System;
using System.IO;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.Log;
using Xunit;
@ -20,7 +20,7 @@ namespace Squidex.Infrastructure.Assets
public override FolderAssetStore CreateStore()
{
return new FolderAssetStore(testFolder, new Mock<ISemanticLog>().Object);
return new FolderAssetStore(testFolder, A.Dummy<ISemanticLog>());
}
public override void Dispose()
@ -34,7 +34,7 @@ namespace Squidex.Infrastructure.Assets
[Fact]
public void Should_throw_when_creating_directory_failed()
{
Assert.Throws<ConfigurationException>(() => new FolderAssetStore(CreateInvalidPath(), new Mock<ISemanticLog>().Object).Connect());
Assert.Throws<ConfigurationException>(() => new FolderAssetStore(CreateInvalidPath(), A.Dummy<ISemanticLog>()).Connect());
}
[Fact]

64
tests/Squidex.Infrastructure.Tests/CQRS/Commands/AggregateHandlerTests.cs

@ -9,7 +9,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Tasks;
using Xunit;
@ -48,8 +48,8 @@ namespace Squidex.Infrastructure.CQRS.Commands
}
}
private readonly Mock<IDomainObjectFactory> factory = new Mock<IDomainObjectFactory>();
private readonly Mock<IDomainObjectRepository> repository = new Mock<IDomainObjectRepository>();
private readonly IDomainObjectFactory factory = A.Fake<IDomainObjectFactory>();
private readonly IDomainObjectRepository repository = A.Fake<IDomainObjectRepository>();
private readonly Envelope<IEvent> event1 = new Envelope<IEvent>(new MyEvent());
private readonly Envelope<IEvent> event2 = new Envelope<IEvent>(new MyEvent());
private readonly CommandContext context;
@ -59,7 +59,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
public AggregateHandlerTests()
{
sut = new AggregateHandler(factory.Object, repository.Object);
sut = new AggregateHandler(factory, repository);
domainObject =
new MyDomainObject(Guid.NewGuid(), 1)
@ -73,31 +73,29 @@ namespace Squidex.Infrastructure.CQRS.Commands
[Fact]
public void Should_provide_access_to_factory()
{
Assert.Equal(factory.Object, sut.Factory);
Assert.Equal(factory, sut.Factory);
}
[Fact]
public void Should_provide_access_to_repository()
{
Assert.Equal(repository.Object, sut.Repository);
Assert.Equal(repository, sut.Repository);
}
[Fact]
public Task Create_async_should_throw_exception_if_not_aggregate_command()
{
return Assert.ThrowsAnyAsync<ArgumentException>(() => sut.CreateAsync<MyDomainObject>(new CommandContext(new Mock<ICommand>().Object), x => TaskHelper.False));
return Assert.ThrowsAnyAsync<ArgumentException>(() => sut.CreateAsync<MyDomainObject>(new CommandContext(A.Dummy<ICommand>()), x => TaskHelper.False));
}
[Fact]
public async Task Create_async_should_create_domain_object_and_save()
{
factory.Setup(x => x.CreateNew(typeof(MyDomainObject), domainObject.Id))
.Returns(domainObject)
.Verifiable();
A.CallTo(() => factory.CreateNew(typeof(MyDomainObject), domainObject.Id))
.Returns(domainObject);
repository.Setup(x => x.SaveAsync(domainObject, It.IsAny<ICollection<Envelope<IEvent>>>(), It.IsAny<Guid>()))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored))
.Returns(TaskHelper.Done);
MyDomainObject passedDomainObject = null;
@ -111,19 +109,17 @@ namespace Squidex.Infrastructure.CQRS.Commands
Assert.Equal(domainObject, passedDomainObject);
Assert.NotNull(context.Result<EntityCreatedResult<Guid>>());
repository.VerifyAll();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored)).MustHaveHappened();
}
[Fact]
public async Task Create_sync_should_create_domain_object_and_save()
{
factory.Setup(x => x.CreateNew(typeof(MyDomainObject), domainObject.Id))
.Returns(domainObject)
.Verifiable();
A.CallTo(() => factory.CreateNew(typeof(MyDomainObject), domainObject.Id))
.Returns(domainObject);
repository.Setup(x => x.SaveAsync(domainObject, It.IsAny<ICollection<Envelope<IEvent>>>(), It.IsAny<Guid>()))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored))
.Returns(TaskHelper.Done);
MyDomainObject passedDomainObject = null;
@ -135,25 +131,23 @@ namespace Squidex.Infrastructure.CQRS.Commands
Assert.Equal(domainObject, passedDomainObject);
Assert.NotNull(context.Result<EntityCreatedResult<Guid>>());
repository.VerifyAll();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored)).MustHaveHappened();
}
[Fact]
public Task Update_async_should_throw_exception_if_not_aggregate_command()
{
return Assert.ThrowsAnyAsync<ArgumentException>(() => sut.UpdateAsync<MyDomainObject>(new CommandContext(new Mock<ICommand>().Object), x => TaskHelper.False));
return Assert.ThrowsAnyAsync<ArgumentException>(() => sut.UpdateAsync<MyDomainObject>(new CommandContext(A.Dummy<ICommand>()), x => TaskHelper.False));
}
[Fact]
public async Task Update_async_should_create_domain_object_and_save()
{
repository.Setup(x => x.GetByIdAsync<MyDomainObject>(command.AggregateId, null))
.Returns(Task.FromResult(domainObject))
.Verifiable();
A.CallTo(() => repository.GetByIdAsync<MyDomainObject>(command.AggregateId, null))
.Returns(Task.FromResult(domainObject));
repository.Setup(x => x.SaveAsync(domainObject, It.IsAny<ICollection<Envelope<IEvent>>>(), It.IsAny<Guid>()))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored))
.Returns(TaskHelper.Done);
MyDomainObject passedDomainObject = null;
@ -167,19 +161,17 @@ namespace Squidex.Infrastructure.CQRS.Commands
Assert.Equal(domainObject, passedDomainObject);
Assert.NotNull(context.Result<EntitySavedResult>());
repository.VerifyAll();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored)).MustHaveHappened();
}
[Fact]
public async Task Update_sync_should_create_domain_object_and_save()
{
repository.Setup(x => x.GetByIdAsync<MyDomainObject>(command.AggregateId, null))
.Returns(Task.FromResult(domainObject))
.Verifiable();
A.CallTo(() => repository.GetByIdAsync<MyDomainObject>(command.AggregateId, null))
.Returns(Task.FromResult(domainObject));
repository.Setup(x => x.SaveAsync(domainObject, It.IsAny<ICollection<Envelope<IEvent>>>(), It.IsAny<Guid>()))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored))
.Returns(TaskHelper.Done);
MyDomainObject passedDomainObject = null;
@ -191,7 +183,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
Assert.Equal(domainObject, passedDomainObject);
Assert.NotNull(context.Result<EntitySavedResult>());
repository.VerifyAll();
A.CallTo(() => repository.SaveAsync(domainObject, A<ICollection<Envelope<IEvent>>>.Ignored, A<Guid>.Ignored)).MustHaveHappened();
}
}
}

4
tests/Squidex.Infrastructure.Tests/CQRS/Commands/CommandContextTests.cs

@ -7,14 +7,14 @@
// ==========================================================================
using System;
using Moq;
using FakeItEasy;
using Xunit;
namespace Squidex.Infrastructure.CQRS.Commands
{
public class CommandContextTests
{
private readonly ICommand command = new Mock<ICommand>().Object;
private readonly ICommand command = A.Dummy<ICommand>();
[Fact]
public void Should_instantiate_and_provide_command()

16
tests/Squidex.Infrastructure.Tests/CQRS/Commands/DefaultDomainObjectFactoryTests.cs

@ -7,7 +7,7 @@
// ==========================================================================
using System;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.CQRS.Events;
using Xunit;
@ -17,6 +17,8 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
public class DefaultDomainObjectFactoryTests
{
private readonly IServiceProvider serviceProvider = A.Fake<IServiceProvider>();
private sealed class DO : DomainObjectBase
{
public DO(Guid id, int version)
@ -32,17 +34,15 @@ namespace Squidex.Infrastructure.CQRS.Commands
[Fact]
public void Should_create_domain_object_with_autofac()
{
var serviceProvider = new Mock<IServiceProvider>();
var factoryFunction = new DomainObjectFactoryFunction<DO>(passedId =>
{
return new DO(passedId, -1);
});
serviceProvider.Setup(x => x.GetService(typeof(DomainObjectFactoryFunction<DO>)))
A.CallTo(() => serviceProvider.GetService(typeof(DomainObjectFactoryFunction<DO>)))
.Returns(factoryFunction);
var sut = new DefaultDomainObjectFactory(serviceProvider.Object);
var sut = new DefaultDomainObjectFactory(serviceProvider);
var id = Guid.NewGuid();
@ -55,17 +55,17 @@ namespace Squidex.Infrastructure.CQRS.Commands
[Fact]
public void Should_throw_exception_if_new_entity_has_invalid_version()
{
var serviceProvider = new Mock<IServiceProvider>();
var serviceProvider = A.Fake<IServiceProvider>();
var factoryFunction = new DomainObjectFactoryFunction<DO>(passedId =>
{
return new DO(passedId, 0);
});
serviceProvider.Setup(x => x.GetService(typeof(DomainObjectFactoryFunction<DO>)))
A.CallTo(() => serviceProvider.GetService(typeof(DomainObjectFactoryFunction<DO>)))
.Returns(factoryFunction);
var sut = new DefaultDomainObjectFactory(serviceProvider.Object);
var sut = new DefaultDomainObjectFactory(serviceProvider);
Assert.Throws<InvalidOperationException>(() => sut.CreateNew(typeof(DO), Guid.NewGuid()));
}

63
tests/Squidex.Infrastructure.Tests/CQRS/Commands/DefaultDomainObjectRepositoryTests.cs

@ -9,7 +9,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Tasks;
using Xunit;
@ -21,10 +21,10 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
public class DefaultDomainObjectRepositoryTests
{
private readonly Mock<IDomainObjectFactory> factory = new Mock<IDomainObjectFactory>();
private readonly Mock<IEventStore> eventStore = new Mock<IEventStore>();
private readonly Mock<IStreamNameResolver> streamNameResolver = new Mock<IStreamNameResolver>();
private readonly Mock<EventDataFormatter> eventDataFormatter = new Mock<EventDataFormatter>(new TypeNameRegistry(), null);
private readonly IDomainObjectFactory factory = A.Fake<IDomainObjectFactory>();
private readonly IEventStore eventStore = A.Fake<IEventStore>();
private readonly IStreamNameResolver streamNameResolver = A.Fake<IStreamNameResolver>();
private readonly EventDataFormatter eventDataFormatter = A.Fake<EventDataFormatter>();
private readonly string streamName = Guid.NewGuid().ToString();
private readonly Guid aggregateId = Guid.NewGuid();
private readonly MyDomainObject domainObject;
@ -34,11 +34,11 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
domainObject = new MyDomainObject(aggregateId, 123);
streamNameResolver.Setup(x => x.GetStreamName(It.IsAny<Type>(), aggregateId)).Returns(streamName);
A.CallTo(() => streamNameResolver.GetStreamName(A<Type>.Ignored, aggregateId)).Returns(streamName);
factory.Setup(x => x.CreateNew(typeof(MyDomainObject), aggregateId)).Returns(domainObject);
A.CallTo(() => factory.CreateNew(typeof(MyDomainObject), aggregateId)).Returns(domainObject);
sut = new DefaultDomainObjectRepository(factory.Object, eventStore.Object, streamNameResolver.Object, eventDataFormatter.Object);
sut = new DefaultDomainObjectRepository(factory, eventStore, streamNameResolver, eventDataFormatter);
}
public sealed class MyEvent : IEvent
@ -72,7 +72,8 @@ namespace Squidex.Infrastructure.CQRS.Commands
[Fact]
public async Task Should_throw_exception_when_event_store_returns_no_events()
{
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(Task.FromResult<IReadOnlyList<StoredEvent>>(new List<StoredEvent>()));
A.CallTo(() => eventStore.GetEventsAsync(streamName))
.Returns(Task.FromResult<IReadOnlyList<StoredEvent>>(new List<StoredEvent>()));
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.GetByIdAsync<MyDomainObject>(aggregateId));
}
@ -92,10 +93,13 @@ namespace Squidex.Infrastructure.CQRS.Commands
new StoredEvent("1", 1, eventData2)
};
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(Task.FromResult<IReadOnlyList<StoredEvent>>(events));
A.CallTo(() => eventStore.GetEventsAsync(streamName))
.Returns(Task.FromResult<IReadOnlyList<StoredEvent>>(events));
eventDataFormatter.Setup(x => x.Parse(eventData1)).Returns(new Envelope<IEvent>(event1));
eventDataFormatter.Setup(x => x.Parse(eventData2)).Returns(new Envelope<IEvent>(event2));
A.CallTo(() => eventDataFormatter.Parse(eventData1))
.Returns(new Envelope<IEvent>(event1));
A.CallTo(() => eventDataFormatter.Parse(eventData2))
.Returns(new Envelope<IEvent>(event2));
var result = await sut.GetByIdAsync<MyDomainObject>(aggregateId);
@ -117,10 +121,13 @@ namespace Squidex.Infrastructure.CQRS.Commands
new StoredEvent("1", 1, eventData2)
};
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(Task.FromResult<IReadOnlyList<StoredEvent>>(events));
A.CallTo(() => eventStore.GetEventsAsync(streamName))
.Returns(Task.FromResult<IReadOnlyList<StoredEvent>>(events));
eventDataFormatter.Setup(x => x.Parse(eventData1)).Returns(new Envelope<IEvent>(event1));
eventDataFormatter.Setup(x => x.Parse(eventData2)).Returns(new Envelope<IEvent>(event2));
A.CallTo(() => eventDataFormatter.Parse(eventData1))
.Returns(new Envelope<IEvent>(event1));
A.CallTo(() => eventDataFormatter.Parse(eventData2))
.Returns(new Envelope<IEvent>(event2));
await Assert.ThrowsAsync<DomainObjectVersionException>(() => sut.GetByIdAsync<MyDomainObject>(aggregateId, 200));
}
@ -136,19 +143,20 @@ namespace Squidex.Infrastructure.CQRS.Commands
var eventData1 = new EventData();
var eventData2 = new EventData();
eventDataFormatter.Setup(x => x.ToEventData(It.Is<Envelope<IEvent>>(e => e.Payload == event1), commitId)).Returns(eventData1);
eventDataFormatter.Setup(x => x.ToEventData(It.Is<Envelope<IEvent>>(e => e.Payload == event2), commitId)).Returns(eventData2);
A.CallTo(() => eventDataFormatter.ToEventData(A<Envelope<IEvent>>.That.Matches(e => e.Payload == event1), commitId))
.Returns(eventData1);
A.CallTo(() => eventDataFormatter.ToEventData(A<Envelope<IEvent>>.That.Matches(e => e.Payload == event2), commitId))
.Returns(eventData2);
eventStore.Setup(x => x.AppendEventsAsync(commitId, streamName, 123, It.Is<ICollection<EventData>>(e => e.Count == 2)))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => eventStore.AppendEventsAsync(commitId, streamName, 123, A<ICollection<EventData>>.That.Matches(e => e.Count == 2)))
.Returns(TaskHelper.Done);
domainObject.AddEvent(event1);
domainObject.AddEvent(event2);
await sut.SaveAsync(domainObject, domainObject.GetUncomittedEvents(), commitId);
eventStore.VerifyAll();
A.CallTo(() => eventStore.AppendEventsAsync(commitId, streamName, 123, A<ICollection<EventData>>.That.Matches(e => e.Count == 2))).MustHaveHappened();
}
[Fact]
@ -162,19 +170,20 @@ namespace Squidex.Infrastructure.CQRS.Commands
var eventData1 = new EventData();
var eventData2 = new EventData();
eventDataFormatter.Setup(x => x.ToEventData(It.Is<Envelope<IEvent>>(e => e.Payload == event1), commitId)).Returns(eventData1);
eventDataFormatter.Setup(x => x.ToEventData(It.Is<Envelope<IEvent>>(e => e.Payload == event2), commitId)).Returns(eventData2);
A.CallTo(() => eventDataFormatter.ToEventData(A<Envelope<IEvent>>.That.Matches(e => e.Payload == event1), commitId))
.Returns(eventData1);
A.CallTo(() => eventDataFormatter.ToEventData(A<Envelope<IEvent>>.That.Matches(e => e.Payload == event2), commitId))
.Returns(eventData2);
eventStore.Setup(x => x.AppendEventsAsync(commitId, streamName, 123, new List<EventData> { eventData1, eventData2 }))
.Throws(new WrongEventVersionException(1, 2))
.Verifiable();
A.CallTo(() => eventStore.AppendEventsAsync(commitId, streamName, 123, A<ICollection<EventData>>.That.Matches(e => e.Count == 2)))
.Throws(new WrongEventVersionException(1, 2));
domainObject.AddEvent(event1);
domainObject.AddEvent(event2);
await Assert.ThrowsAsync<DomainObjectVersionException>(() => sut.SaveAsync(domainObject, domainObject.GetUncomittedEvents(), commitId));
eventStore.VerifyAll();
A.CallTo(() => eventStore.AppendEventsAsync(commitId, streamName, 123, A<ICollection<EventData>>.That.Matches(e => e.Count == 2))).MustHaveHappened();
}
}
}

15
tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs

@ -7,7 +7,7 @@
// ==========================================================================
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using NodaTime;
using Xunit;
@ -22,15 +22,16 @@ namespace Squidex.Infrastructure.CQRS.Commands
public long? ExpectedVersion { get; set; }
}
private readonly Mock<IClock> clock = new Mock<IClock>();
private readonly IClock clock = A.Fake<IClock>();
[Fact]
public async Task Should_set_timestamp_for_timestamp_command()
{
var utc = Instant.FromUnixTimeSeconds(1000);
var sut = new EnrichWithTimestampHandler(clock.Object);
var sut = new EnrichWithTimestampHandler(clock);
clock.Setup(x => x.GetCurrentInstant()).Returns(utc);
A.CallTo(() => clock.GetCurrentInstant())
.Returns(utc);
var command = new MyTimestampCommand();
@ -43,13 +44,13 @@ namespace Squidex.Infrastructure.CQRS.Commands
[Fact]
public async Task Should_do_nothing_for_normal_command()
{
var sut = new EnrichWithTimestampHandler(clock.Object);
var sut = new EnrichWithTimestampHandler(clock);
var result = await sut.HandleAsync(new CommandContext(new Mock<ICommand>().Object));
var result = await sut.HandleAsync(new CommandContext(A.Dummy<ICommand>()));
Assert.False(result);
clock.Verify(x => x.GetCurrentInstant(), Times.Never());
A.CallTo(() => clock.GetCurrentInstant()).MustNotHaveHappened();
}
}
}

4
tests/Squidex.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs

@ -8,7 +8,7 @@
using System;
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.Tasks;
using Xunit;
@ -16,7 +16,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
public class InMemoryCommandBusTests
{
private readonly ICommand command = new Mock<ICommand>().Object;
private readonly ICommand command = A.Fake<ICommand>();
private sealed class HandledHandler : ICommandHandler
{

4
tests/Squidex.Infrastructure.Tests/CQRS/Commands/LogExceptionHandlerTests.cs

@ -10,7 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.Log;
using Xunit;
@ -20,7 +20,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
private readonly MyLog log = new MyLog();
private readonly LogExceptionHandler sut;
private readonly ICommand command = new Mock<ICommand>().Object;
private readonly ICommand command = A.Dummy<ICommand>();
private sealed class MyLog : ISemanticLog
{

4
tests/Squidex.Infrastructure.Tests/CQRS/Commands/LogExecutingHandlerTests.cs

@ -8,7 +8,7 @@
using System;
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.Log;
using Xunit;
@ -18,7 +18,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
private readonly MyLog log = new MyLog();
private readonly LogExecutingHandler sut;
private readonly ICommand command = new Mock<ICommand>().Object;
private readonly ICommand command = A.Dummy<ICommand>();
private sealed class MyLog : ISemanticLog
{

56
tests/Squidex.Infrastructure.Tests/CQRS/Events/CompoundEventConsumerTests.cs

@ -7,7 +7,7 @@
// ==========================================================================
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.Tasks;
using Xunit;
@ -15,8 +15,8 @@ namespace Squidex.Infrastructure.CQRS.Events
{
public class CompoundEventConsumerTests
{
private readonly Mock<IEventConsumer> consumer1 = new Mock<IEventConsumer>();
private readonly Mock<IEventConsumer> consumer2 = new Mock<IEventConsumer>();
private readonly IEventConsumer consumer1 = A.Fake<IEventConsumer>();
private readonly IEventConsumer consumer2 = A.Fake<IEventConsumer>();
private sealed class MyEvent : IEvent
{
@ -25,7 +25,7 @@ namespace Squidex.Infrastructure.CQRS.Events
[Fact]
public void Should_return_given_name()
{
var sut = new CompoundEventConsumer("consumer-name", consumer1.Object);
var sut = new CompoundEventConsumer("consumer-name", consumer1);
Assert.Equal("consumer-name", sut.Name);
}
@ -33,9 +33,9 @@ namespace Squidex.Infrastructure.CQRS.Events
[Fact]
public void Should_return_first_inner_name()
{
consumer1.Setup(x => x.Name).Returns("my-inner-consumer");
A.CallTo(() => consumer1.Name).Returns("my-inner-consumer");
var sut = new CompoundEventConsumer(consumer1.Object, consumer2.Object);
var sut = new CompoundEventConsumer(consumer1, consumer2);
Assert.Equal("my-inner-consumer", sut.Name);
}
@ -43,10 +43,10 @@ namespace Squidex.Infrastructure.CQRS.Events
[Fact]
public void Should_return_compound_filter()
{
consumer1.Setup(x => x.EventsFilter).Returns("filter1");
consumer2.Setup(x => x.EventsFilter).Returns("filter2");
A.CallTo(() => consumer1.EventsFilter).Returns("filter1");
A.CallTo(() => consumer2.EventsFilter).Returns("filter2");
var sut = new CompoundEventConsumer("my", consumer1.Object, consumer2.Object);
var sut = new CompoundEventConsumer("my", consumer1, consumer2);
Assert.Equal("(filter1)|(filter2)", sut.EventsFilter);
}
@ -54,10 +54,10 @@ namespace Squidex.Infrastructure.CQRS.Events
[Fact]
public void Should_ignore_empty_filters()
{
consumer1.Setup(x => x.EventsFilter).Returns("filter1");
consumer2.Setup(x => x.EventsFilter).Returns("");
A.CallTo(() => consumer1.EventsFilter).Returns("filter1");
A.CallTo(() => consumer2.EventsFilter).Returns("");
var sut = new CompoundEventConsumer("my", consumer1.Object, consumer2.Object);
var sut = new CompoundEventConsumer("my", consumer1, consumer2);
Assert.Equal("(filter1)", sut.EventsFilter);
}
@ -65,20 +65,18 @@ namespace Squidex.Infrastructure.CQRS.Events
[Fact]
public async Task Should_clear_all_consumers()
{
consumer1.Setup(x => x.ClearAsync()).
Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => consumer1.ClearAsync()).
Returns(TaskHelper.Done);
consumer2.Setup(x => x.ClearAsync())
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => consumer2.ClearAsync())
.Returns(TaskHelper.Done);
var sut = new CompoundEventConsumer("consumer-name", consumer1.Object, consumer2.Object);
var sut = new CompoundEventConsumer("consumer-name", consumer1, consumer2);
await sut.ClearAsync();
consumer1.VerifyAll();
consumer2.VerifyAll();
A.CallTo(() => consumer1.ClearAsync()).MustHaveHappened();
A.CallTo(() => consumer2.ClearAsync()).MustHaveHappened();
}
[Fact]
@ -86,20 +84,18 @@ namespace Squidex.Infrastructure.CQRS.Events
{
var @event = Envelope.Create(new MyEvent());
consumer1.Setup(x => x.On(@event))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => consumer1.On(@event))
.Returns(TaskHelper.Done);
consumer2.Setup(x => x.On(@event))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => consumer2.On(@event))
.Returns(TaskHelper.Done);
var sut = new CompoundEventConsumer("consumer-name", consumer1.Object, consumer2.Object);
var sut = new CompoundEventConsumer("consumer-name", consumer1, consumer2);
await sut.On(@event);
consumer1.VerifyAll();
consumer2.VerifyAll();
A.CallTo(() => consumer1.On(@event)).MustHaveHappened();
A.CallTo(() => consumer2.On(@event)).MustHaveHappened();
}
}
}

74
tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs

@ -9,7 +9,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Moq;
using FakeItEasy;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Tasks;
using Xunit;
@ -94,10 +94,10 @@ namespace Squidex.Infrastructure.CQRS.Events
}
}
private readonly Mock<IEventConsumerInfoRepository> eventConsumerInfoRepository = new Mock<IEventConsumerInfoRepository>();
private readonly Mock<IEventConsumer> eventConsumer = new Mock<IEventConsumer>();
private readonly Mock<ISemanticLog> log = new Mock<ISemanticLog>();
private readonly Mock<EventDataFormatter> formatter = new Mock<EventDataFormatter>(new TypeNameRegistry(), null);
private readonly IEventConsumerInfoRepository eventConsumerInfoRepository = A.Fake<IEventConsumerInfoRepository>();
private readonly IEventConsumer eventConsumer = A.Fake<IEventConsumer>();
private readonly ISemanticLog log = A.Fake<ISemanticLog>();
private readonly EventDataFormatter formatter = A.Fake<EventDataFormatter>();
private readonly EventData eventData1 = new EventData();
private readonly EventData eventData2 = new EventData();
private readonly EventData eventData3 = new EventData();
@ -117,29 +117,29 @@ namespace Squidex.Infrastructure.CQRS.Events
new StoredEvent("5", 5, eventData3)
};
consumerName = eventConsumer.Object.GetType().Name;
consumerName = eventConsumer.GetType().Name;
var eventStore = new MyEventStore(events);
eventConsumer.Setup(x => x.Name).Returns(consumerName);
eventConsumerInfoRepository.Setup(x => x.FindAsync(consumerName)).Returns(Task.FromResult<IEventConsumerInfo>(consumerInfo));
A.CallTo(() => eventConsumer.Name).Returns(consumerName);
A.CallTo(() => eventConsumerInfoRepository.FindAsync(consumerName)).Returns(Task.FromResult<IEventConsumerInfo>(consumerInfo));
formatter.Setup(x => x.Parse(eventData1)).Returns(envelope1);
formatter.Setup(x => x.Parse(eventData2)).Returns(envelope2);
formatter.Setup(x => x.Parse(eventData3)).Returns(envelope3);
A.CallTo(() => formatter.Parse(eventData1)).Returns(envelope1);
A.CallTo(() => formatter.Parse(eventData2)).Returns(envelope2);
A.CallTo(() => formatter.Parse(eventData3)).Returns(envelope3);
sut = new EventReceiver(formatter.Object, eventStore, eventConsumerInfoRepository.Object, log.Object);
sut = new EventReceiver(formatter, eventStore, eventConsumerInfoRepository, log);
}
[Fact]
public void Should_only_connect_once()
{
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer);
sut.Subscribe(eventConsumer);
sut.Refresh();
sut.Dispose();
eventConsumerInfoRepository.Verify(x => x.CreateAsync(consumerName), Times.Once());
A.CallTo(() => eventConsumerInfoRepository.CreateAsync(consumerName)).MustHaveHappened();
}
[Fact]
@ -147,13 +147,13 @@ namespace Squidex.Infrastructure.CQRS.Events
{
consumerInfo.Position = "2";
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer);
sut.Refresh();
sut.Dispose();
eventConsumer.Verify(x => x.On(envelope1), Times.Once());
eventConsumer.Verify(x => x.On(envelope2), Times.Once());
eventConsumer.Verify(x => x.On(envelope3), Times.Once());
A.CallTo(() => eventConsumer.On(envelope1)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope2)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope3)).MustHaveHappened();
}
[Fact]
@ -161,18 +161,18 @@ namespace Squidex.Infrastructure.CQRS.Events
{
consumerInfo.Position = "2";
eventConsumer.Setup(x => x.On(envelope1)).Returns(TaskHelper.True);
eventConsumer.Setup(x => x.On(envelope2)).Throws(new InvalidOperationException());
A.CallTo(() => eventConsumer.On(envelope1)).Returns(TaskHelper.True);
A.CallTo(() => eventConsumer.On(envelope2)).Throws(new InvalidOperationException());
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer);
sut.Refresh();
sut.Dispose();
eventConsumer.Verify(x => x.On(envelope1), Times.Once());
eventConsumer.Verify(x => x.On(envelope2), Times.Once());
eventConsumer.Verify(x => x.On(envelope3), Times.Never());
A.CallTo(() => eventConsumer.On(envelope1)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope2)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope3)).MustNotHaveHappened();
eventConsumerInfoRepository.Verify(x => x.StopAsync(consumerName, It.IsAny<string>()), Times.Once());
A.CallTo(() => eventConsumerInfoRepository.StopAsync(consumerName, A<string>.Ignored)).MustHaveHappened();
}
[Fact]
@ -180,17 +180,17 @@ namespace Squidex.Infrastructure.CQRS.Events
{
consumerInfo.Position = "2";
formatter.Setup(x => x.Parse(eventData2)).Throws(new InvalidOperationException());
A.CallTo(() => formatter.Parse(eventData2)).Throws(new InvalidOperationException());
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer);
sut.Refresh();
sut.Dispose();
eventConsumer.Verify(x => x.On(envelope1), Times.Once());
eventConsumer.Verify(x => x.On(envelope2), Times.Never());
eventConsumer.Verify(x => x.On(envelope3), Times.Never());
A.CallTo(() => eventConsumer.On(envelope1)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope2)).MustNotHaveHappened();
A.CallTo(() => eventConsumer.On(envelope3)).MustNotHaveHappened();
eventConsumerInfoRepository.Verify(x => x.StopAsync(consumerName, It.IsAny<string>()), Times.Once());
A.CallTo(() => eventConsumerInfoRepository.StopAsync(consumerName, A<string>.Ignored)).MustHaveHappened();
}
[Fact]
@ -199,15 +199,15 @@ namespace Squidex.Infrastructure.CQRS.Events
consumerInfo.IsResetting = true;
consumerInfo.Position = "2";
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer);
sut.Refresh();
sut.Dispose();
eventConsumer.Verify(x => x.On(envelope1), Times.Once());
eventConsumer.Verify(x => x.On(envelope2), Times.Once());
eventConsumer.Verify(x => x.On(envelope3), Times.Once());
A.CallTo(() => eventConsumer.On(envelope1)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope2)).MustHaveHappened();
A.CallTo(() => eventConsumer.On(envelope3)).MustHaveHappened();
eventConsumer.Verify(x => x.ClearAsync(), Times.Once());
A.CallTo(() => eventConsumer.ClearAsync()).MustHaveHappened();
}
}
}

28
tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs

@ -6,9 +6,9 @@
// All rights reserved.
// ==========================================================================
using FakeItEasy;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
// ReSharper disable RedundantAssignment
@ -27,13 +27,13 @@ namespace Squidex.Infrastructure.Caching
public T Value { get; }
}
private readonly Mock<IPubSub> pubsub = new Mock<IPubSub>();
private readonly Mock<IMemoryCache> cache = new Mock<IMemoryCache>();
private readonly IPubSub pubsub = A.Fake<IPubSub>();
private readonly IMemoryCache cache = A.Fake<IMemoryCache>();
private readonly InvalidatingMemoryCache sut;
public InvalidatingMemoryCacheTest()
{
sut = new InvalidatingMemoryCache(cache.Object, pubsub.Object);
sut = new InvalidatingMemoryCache(cache, pubsub);
}
[Fact]
@ -47,7 +47,7 @@ namespace Squidex.Infrastructure.Caching
{
sut.Dispose();
cache.Verify(x => x.Dispose(), Times.Once());
A.CallTo(() => cache.Dispose()).MustHaveHappened();
}
[Fact]
@ -55,7 +55,7 @@ namespace Squidex.Infrastructure.Caching
{
sut.Remove("a-key");
cache.Verify(x => x.Remove("a-key"), Times.Once());
A.CallTo(() => cache.Remove("a-key")).MustHaveHappened();
}
[Fact]
@ -63,7 +63,7 @@ namespace Squidex.Infrastructure.Caching
{
sut.Invalidate(123);
pubsub.Verify(x => x.Publish("CacheInvalidations", It.IsAny<string>(), true), Times.Never());
A.CallTo(() => pubsub.Publish("CacheInvalidations", A<string>.Ignored, true)).MustNotHaveHappened();
}
[Fact]
@ -71,7 +71,7 @@ namespace Squidex.Infrastructure.Caching
{
sut.Invalidate("a-key");
pubsub.Verify(x => x.Publish("CacheInvalidations", "a-key", true), Times.Once());
A.CallTo(() => pubsub.Publish("CacheInvalidations", "a-key", true)).MustHaveHappened();
}
[Fact]
@ -79,20 +79,20 @@ namespace Squidex.Infrastructure.Caching
{
((IMemoryCache)sut).Invalidate("a-key");
pubsub.Verify(x => x.Publish("CacheInvalidations", "a-key", true), Times.Once());
A.CallTo(() => pubsub.Publish("CacheInvalidations", "a-key", true)).MustHaveHappened();
}
[Fact]
public void Should_call_inner_to_create_value()
{
var cacheEntry = new Mock<ICacheEntry>();
var cacheEntry = A.Dummy<ICacheEntry>();
cache.Setup(x => x.CreateEntry("a-key"))
.Returns(cacheEntry.Object);
A.CallTo(() => cache.CreateEntry("a-key"))
.Returns(cacheEntry);
var result = sut.CreateEntry("a-key");
Assert.Equal(cacheEntry.Object, result);
Assert.Equal(cacheEntry, result);
}
[Fact]
@ -100,7 +100,7 @@ namespace Squidex.Infrastructure.Caching
{
object currentOut = 123;
cache.Setup(x => x.TryGetValue("a-key", out currentOut))
A.CallTo(() => cache.TryGetValue("a-key", out currentOut))
.Returns(true);
var exists = sut.TryGetValue("a-key", out object result);

12
tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs

@ -8,8 +8,8 @@
using System;
using System.Collections.Generic;
using FakeItEasy;
using Microsoft.Extensions.Logging;
using Moq;
using Squidex.Infrastructure.Log.Adapter;
using Xunit;
@ -19,7 +19,7 @@ namespace Squidex.Infrastructure.Log
{
private readonly List<ILogChannel> channels = new List<ILogChannel>();
private readonly Lazy<SemanticLog> log;
private readonly Mock<ILogChannel> channel = new Mock<ILogChannel>();
private readonly ILogChannel channel = A.Fake<ILogChannel>();
private readonly SemanticLogLoggerProvider sut;
private string output;
@ -30,13 +30,13 @@ namespace Squidex.Infrastructure.Log
public SemanticLogAdapterTests()
{
channels.Add(channel.Object);
channels.Add(channel);
channel.Setup(x => x.Log(It.IsAny<SemanticLogLevel>(), It.IsAny<string>())).Callback(
new Action<SemanticLogLevel, string>((level, message) =>
A.CallTo(() => channel.Log(A<SemanticLogLevel>.Ignored, A<string>.Ignored))
.Invokes((SemanticLogLevel level, string message) =>
{
output = message;
}));
});
log = new Lazy<SemanticLog>(() => new SemanticLog(channels, new List<ILogAppender>(), () => new JsonLogWriter()));

12
tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs

@ -8,8 +8,8 @@
using System;
using System.Collections.Generic;
using FakeItEasy;
using Microsoft.Extensions.Logging;
using Moq;
using Squidex.Infrastructure.Log.Adapter;
using Xunit;
@ -20,7 +20,7 @@ namespace Squidex.Infrastructure.Log
private readonly List<ILogAppender> appenders = new List<ILogAppender>();
private readonly List<ILogChannel> channels = new List<ILogChannel>();
private readonly Lazy<SemanticLog> log;
private readonly Mock<ILogChannel> channel = new Mock<ILogChannel>();
private readonly ILogChannel channel = A.Fake<ILogChannel>();
private string output;
public SemanticLog Log
@ -30,13 +30,13 @@ namespace Squidex.Infrastructure.Log
public SemanticLogTests()
{
channels.Add(channel.Object);
channels.Add(channel);
channel.Setup(x => x.Log(It.IsAny<SemanticLogLevel>(), It.IsAny<string>())).Callback(
new Action<SemanticLogLevel, string>((level, message) =>
A.CallTo(() => channel.Log(A<SemanticLogLevel>.Ignored, A<string>.Ignored))
.Invokes((SemanticLogLevel level, string message) =>
{
output = message;
}));
});
log = new Lazy<SemanticLog>(() => new SemanticLog(channels, appenders, () => new JsonLogWriter()));
}

2
tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj

@ -10,12 +10,12 @@
<ProjectReference Include="..\..\src\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FakeItEasy" Version="4.0.0" />
<PackageReference Include="FluentAssertions" Version="4.19.3" />
<PackageReference Include="Google.Cloud.Storage.V1" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="Moq" Version="4.7.99" />
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />

35
tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs

@ -9,8 +9,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FakeItEasy;
using FluentAssertions;
using Moq;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Tasks;
using Xunit;
@ -19,13 +19,13 @@ namespace Squidex.Infrastructure.UsageTracking
{
public class BackgroundUsageTrackerTests
{
private readonly Mock<IUsageStore> usageStore = new Mock<IUsageStore>();
private readonly Mock<ISemanticLog> log = new Mock<ISemanticLog>();
private readonly IUsageStore usageStore = A.Fake<IUsageStore>();
private readonly ISemanticLog log = A.Fake<ISemanticLog>();
private readonly BackgroundUsageTracker sut;
public BackgroundUsageTrackerTests()
{
sut = new BackgroundUsageTracker(usageStore.Object, log.Object);
sut = new BackgroundUsageTracker(usageStore, log);
}
[Fact]
@ -65,7 +65,8 @@ namespace Squidex.Infrastructure.UsageTracking
new StoredUsage(date.AddDays(7), 17, 22)
};
usageStore.Setup(x => x.QueryAsync("key", new DateTime(2016, 1, 1), new DateTime(2016, 1, 31))).Returns(Task.FromResult(originalData));
A.CallTo(() => usageStore.QueryAsync("key", new DateTime(2016, 1, 1), new DateTime(2016, 1, 31)))
.Returns(Task.FromResult(originalData));
var result = await sut.GetMonthlyCalls("key", date);
@ -86,7 +87,8 @@ namespace Squidex.Infrastructure.UsageTracking
new StoredUsage(dateFrom.AddDays(7), 17, 22)
};
usageStore.Setup(x => x.QueryAsync("key", dateFrom, dateTo)).Returns(Task.FromResult(originalData));
A.CallTo(() => usageStore.QueryAsync("key", dateFrom, dateTo))
.Returns(Task.FromResult(originalData));
var result = await sut.QueryAsync("key", dateFrom, dateTo);
@ -113,7 +115,7 @@ namespace Squidex.Infrastructure.UsageTracking
await Task.Delay(100);
usageStore.Verify(x => x.TrackUsagesAsync(It.IsAny<DateTime>(), It.IsAny<string>(), It.IsAny<double>(), It.IsAny<long>()), Times.Never());
A.CallTo(() => usageStore.TrackUsagesAsync(A<DateTime>.Ignored, A<string>.Ignored, A<double>.Ignored, A<long>.Ignored)).MustNotHaveHappened();
}
[Fact]
@ -121,17 +123,14 @@ namespace Squidex.Infrastructure.UsageTracking
{
var today = DateTime.Today;
usageStore.Setup(x => x.TrackUsagesAsync(today, "key1", 1.0, 1000))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => usageStore.TrackUsagesAsync(today, "key1", 1.0, 1000))
.Returns(TaskHelper.Done);
usageStore.Setup(x => x.TrackUsagesAsync(today, "key2", 1.5, 5000))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => usageStore.TrackUsagesAsync(today, "key2", 1.5, 5000))
.Returns(TaskHelper.Done);
usageStore.Setup(x => x.TrackUsagesAsync(today, "key3", 0.9, 15000))
.Returns(TaskHelper.Done)
.Verifiable();
A.CallTo(() => usageStore.TrackUsagesAsync(today, "key3", 0.9, 15000))
.Returns(TaskHelper.Done);
await sut.TrackAsync("key1", 1, 1000);
@ -148,7 +147,9 @@ namespace Squidex.Infrastructure.UsageTracking
sut.Dispose();
usageStore.VerifyAll();
A.CallTo(() => usageStore.TrackUsagesAsync(today, "key1", 1.0, 1000)).MustHaveHappened();
A.CallTo(() => usageStore.TrackUsagesAsync(today, "key2", 1.5, 5000)).MustHaveHappened();
A.CallTo(() => usageStore.TrackUsagesAsync(today, "key3", 0.9, 15000)).MustHaveHappened();
}
}
}

Loading…
Cancel
Save